我正在尝试实现一个协议扩展JsonProcess,它有一个以NSData作为参数的函数,我想使用像这样的自我要求创建不同的协议扩展
extension JSONResource where Self: Login {
func proccessJSON(data: NSData) -> Self{
return Login()
}
}
但编译器显示错误
无法转换类型'登录'的返回表达式返回类型' Self'
Login类定义如下
class Login: NSObject {
var username: String?
var firstName: String?
}
如果我序列化NSData并创建一个Login类的isntanse填充它并尝试返回它,我应该在这里返回什么?
答案 0 :(得分:1)
由于您指定扩展仅适用于符合对象Self
为类Login
的情况,因此您应该像这样编写扩展名:
extension JSONResource where Self: Login {
func proccessJSON(data: NSData) -> Login {
return Login()
}
}
答案 1 :(得分:1)
这里的问题是 pasteVideoURL = [UIPasteboard generalPasteboard];
NSString *stringURL = pasteVideoURL.string;
popUpTextField.text = stringURL;
可能比Self
更具特定类型。假设您创建了Login
的子类:
Login
现在,当您在class TopSecretLogin : Login {
var topSecret : String?
}
的实例上使用协议扩展时(假设TopSecretLogin
首先符合Login
) - 您的JSONResource
方法会说明它返回processJSON
,在这种情况下为Self
。但是,您正在尝试返回TopSecretLogin
。因此,编译器不满意,因为您无法将超类传递给期望其子类的东西。
解决方案取决于您是否打算将Login
子类化。如果您不打算将其子类化,则只需将方法签名更改为返回Login
,然后将Login
设为Login
。
如果您打算这样做,则需要向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()