试图符合StringLiteralConvertible

时间:2014-11-08 20:39:45

标签: swift protocols

我在尝试遵守StringLiteralConvertible时遇到了一些奇怪的事情:

class Person: StringLiteralConvertible {
    var name = ""

    init(name n:String){
        name = n
    }

    init(stringLiteral value: StringLiteralType){
        name = n
    }

    init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType){
        name = n
    }

    init(unicodeScalarLiteral value: UnicodeScalarLiteralType){
        name = n
    }
}




var ironMan = Person(name: "Tony Stark")
var spiderMan: Person = "Peter Parker"

我实施了ExtendedGraphemeClusterLiteralConvertibleUnicodeScalarLiteralConvertible协议(无论在地球上是什么意思)。

但是我仍然遇到错误,必须为ExtendedGraphemeClusterLiteralTypeUnicodeScalarLiteralType提供定义:

typealias ExtendedGraphemeClusterLiteralType = String
typealias UnicodeScalarLiteralType = String

为什么我必须提供这个,如果它已经在标准标题???

编译器认为它仍然有权投诉并强迫我将required关键字添加到inits中,即使协议的定义不包含required关键字!为什么????

以下代码编译,但我不明白为什么第一个版本没有编译!

class Person: StringLiteralConvertible {
    var name = ""

    init(name n:String){
        name = n
    }

    typealias ExtendedGraphemeClusterLiteralType = String
    typealias UnicodeScalarLiteralType = String

    required convenience init(stringLiteral value: StringLiteralType){
        self.init(name: value)
    }

    required convenience init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType){
        self.init(name: value)
    }

    required convenience init(unicodeScalarLiteral value: UnicodeScalarLiteralType){
        self.init(name: value)
    }
}
斯威夫特,如果你喜欢编译器对你大吼大叫,你会爱上它! :-P

1 个答案:

答案 0 :(得分:6)

为什么选择typealases:

第一个问题的答案在于,具有关联类型的Swift协议可以被认为是抽象的,并且需要绑定到特定类型。关联类型是使用更专业的方法(如类MyClass)的替代方法:IsCompatibleWith< Int> {}。我认为这样做的原因是具有共同的层次结构,但这种限制也会引起许多其他问题。无论如何,您需要指定协议绑定的类型,这是合理的。在Swift中,您可以通过类型别名关联类型到您想要的类型(在您的情况下为String)。

另请注意,协议中未指定关联类型,协议仅指定您必须定义它。也就是说,除非你的类上有相互冲突的方法,编译器通常可以推断出相关的类型(在某处的文档中阅读)。

必需的初始值设定项:

默认情况下,协议中指定的初始化程序似乎是必需的。文档说您可以将它们实现为设计或方便,但这两种方式都是必需的:

  

协议初始化程序要求的类实现

     

您可以在符合标准上实现协议初始化程序要求   class作为指定的初始化程序或便捷初始化程序。   在这两种情况下,您都必须使用标记初始化程序实现   必需的修饰符:

class SomeClass: SomeProtocol {
required init(someParameter: Int) {
// initializer implementation goes here
}
}
     

使用必需的修饰符可确保您提供显式   或者继承所有的初始化程序要求的实现   符合类的子类,使它们也符合   协议

从我的阅读中,它回答what但不回答why