这里的问题是它Self
可能比Login
. 假设您创建了一个子类Login
:
class TopSecretLogin : Login {
var topSecret : String?
}
TopSecretLogin
现在,当您在(假设首先Login
符合)的实例上使用您的协议扩展时JSONResource
- 您的processJSON
方法说它返回Self
,TopSecretLogin
在这种情况下就是这样。但是,您正在尝试返回一个Login
. 因此编译器不高兴,因为您不能将超类传递给期望其子类的东西。
解决方案取决于您是否打算Login
被子类化。如果您不打算将其子类化,则只需将方法签名更改为返回 a Login
,然后制作Login
a final class
。
如果您确实打算这样做,则需要将所需的初始化程序添加到,允许您在协议扩展中Login
构造任意实例。Self
示例设置可能如下所示:
protocol JSONResource {}
class Login : NSObject, JSONResource {
var username: String?
var firstName: String?
required override init() {
super.init()
}
}
class TopSecretLogin : Login {
var topSecret : String?
required init() {
super.init()
}
}
extension JSONResource where Self : Login {
func processJSON(data: NSData) -> Self {
// do some processing...
return Self()
}
}
let someData = // ...
let l = Login()
l.processJSON(someData) // returns Login
let t = TopSecretLogin()
t.processJSON(someData) // returns TopSecretLogin
processJSON
虽然说了这么多,但如果是静态方法而不是实例方法不是更有意义吗?对我来说,它看起来不需要对实例进行操作,它只是从给定的一组NSData
.
您可能还想考虑制定processJSON
协议要求,就像任何JSONResource
应该能够做到的那样processJSON
?在这种情况下,您需要扩展Login
而不是协议本身来实现该方法。self.init()
然后,您可以在静态范围或self.dynamicType.init()
实例范围内创建新实例。
您可能还需要考虑使用初始化程序执行此操作:
protocol JSONResource {
init(jsonData:NSData)
}
class Login : NSObject, JSONResource {
var username: String?
var firstName: String?
required init(jsonData:NSData) {
// do some processing
super.init()
}
}
class TopSecretLogin : Login {
var topSecret : String?
required init(jsonData:NSData) {
// do some processing
super.init(jsonData:jsonData)
}
}
let someData = // ...
let l = Login(jsonData: someData) // returns Login
let t = TopSecretLogin(jsonData: someData) // returns TopSecretLogin