我很难在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
如果我完全偏离协议扩展如何工作以提供默认实现,我就如何实现相同的结果提出了想法。
答案 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