难以理解Swift协议扩展中的“关联类型”

时间:2015-10-11 00:43:49

标签: swift swift-extensions swift-protocols

我很难在swift中理解协议和协议扩展。

我想要定义一系列可以应用于类的协议,以及一组协议扩展来提供默认实现。示例代码:

// MARK: - Protocols & Protocol Extensions
protocol OutputItem {
    typealias ResultType
    func rawValue() -> ResultType
    // other requirements ...
}

protocol StringOutputItem : OutputItem {}
extension StringOutputItem {
    typealias ResultType = String
    override func rawValue() -> Self.ResultType {
        return "string ouput"
    }
}

protocol IntOutputItem: OutputItem {}
extension IntOutputItem {
    typealias ResultType = Int
    override func rawValue() -> Self.ResultType {
        return 123
    }
}

扩展程序中rawValue()的上述覆盖功能会产生错误Ambiguous type name 'ResultType' in 'Self'。如果我从Self删除Self.ResultType,则会收到错误'ResultType' is ambiguous for type lookup in this context

如何向协议扩展发信号通知哪种类型用于ResultType

我的目标是能够将协议及其扩展应用于类,如下所示:

// MARK: - Base Class
class DataItem {
    // Some base class methods
    func randomMethod() -> String {
        return "some random base class method"
    }
}

// MARK: - Subclasses
class StringItem : DataItem, StringOutputItem {
    // Some subclass methods
}

class AnotherStringItem : DataItem, StringOutputItem {
    // Some subclass methods
}

class IntItem : DataItem, IntOutputItem {
    // Some subclass methods
}

那样:

let item1 = StringItem()
print(item1.rawValue())         // should give "string output"

let item2 = AnotherStringItem()
print(item2.rawValue())         // should give "string output"

let item3 = IntItem()
print(item3.rawValue())         // should give 123

如果我完全偏离协议扩展如何工作以提供默认实现,我就如何实现相同的结果提出了想法。

1 个答案:

答案 0 :(得分:0)

Swift编译器通过实现的协议方法的类型签名推断出ResultType的类型。例如,在StringOutputItem的以下声明中,编译器知道StringOutputItem的{​​{1}}类型为ResultType,即使没有明确的声明:

String

我们可以在protocol StringOutputItem: OutputItem {} extension StringOutputItem { func rawValue() -> String { return "string output" } } class StringItem : DataItem, StringOutputItem {} let item = StringItem() print(item.rawValue()) // prints "string output" 中明确声明ResultType,这只会确保StringOutputItem符合StringOutputItem协议并使用正确的类型实现它。

为了说明相关类型的类型推断,假设OutputItem指定另一种方法作为其协议的一部分。如果我们提供类型不匹配的默认实现,编译器将抛出一个错误,指示实现类型不符合协议。

OutputItem

通过在protocol OutputItem { typealias ResultType func rawValue() -> ResultType func printValue(r: ResultType) } protocol StringOutputItem: OutputItem {} extension StringOutputItem { func rawValue() -> String { return "string output" } func printValue(r: Int) { // Should be String ... } } struct Test: StringOutputItem {} // Error: Type 'Test' does not conform to protocol 'OutputItem' 中明确声明typealias ResultType = String,我们确保在实现协议的方法时使用了正确的类型。

StringOutputItem