如何创建一个返回确认类型的协议扩展?

时间:2016-06-06 12:23:21

标签: ios swift swift-protocols protocol-extension

我正在尝试实现一个协议扩展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填充它并尝试返回它,我应该在这里返回什么?

2 个答案:

答案 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()