难以理解Swift协议扩展中的“关联类型”
我正在努力理解swift中的协议和协议扩展 我想定义一系列可应用于类的协议,以及一组提供默认实现的协议扩展。示例代码:难以理解Swift协议扩展中的“关联类型”,swift,swift-extensions,swift-protocols,Swift,Swift Extensions,Swift Protocols,我正在努力理解swift中的协议和协议扩展 我想定义一系列可应用于类的协议,以及一组提供默认实现的协议扩展。示例代码: // MARK: - Protocols & Protocol Extensions protocol OutputItem { typealias ResultType func rawValue() -> ResultType // other requirements ... } protocol StringOutputItem
// 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()
的上述重写函数在'Self'中给出了一个不明确的类型名'ResultType'。如果我从Self.ResultType
中删除Self
,我会得到一个错误“ResultType”对于此上下文中的类型查找是不明确的
如何向协议扩展发送用于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
如果我完全不了解协议扩展如何提供默认实现,我对如何实现相同的结果持开放态度。Swift编译器通过实现的协议方法的类型签名推断出
ResultType
的类型。例如,在下面的StringOutputItem
声明中,编译器知道StringOutputItem
的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"
我们可以在StringOutputItem
中显式声明ResultType
,这将确保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'
通过在StringOutputItem
中显式声明typealias ResultType=String
,我们可以确保在实现协议的方法时使用正确的类型
protocol OutputItem {
typealias ResultType
func rawValue() -> ResultType
func printValue(r: ResultType)
}
protocol StringOutputItem: OutputItem {}
extension StringOutputItem {
typealias ResultType = String // without this typealias declaration, the program WILL compile since ResultType is inferred to be of type Int
func rawValue() -> Int {
return 123
}
func printValue(r: Int) {
...
}
}
struct Test: StringOutputItem {} // Error: Type 'Test' does not conform to protocol 'OutputItem'
Swift编译器通过实现的协议方法的类型签名推断出
ResultType
的类型。例如,在下面的StringOutputItem
声明中,编译器知道StringOutputItem
的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"
我们可以在StringOutputItem
中显式声明ResultType
,这将确保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'
通过在StringOutputItem
中显式声明typealias ResultType=String
,我们可以确保在实现协议的方法时使用正确的类型
protocol OutputItem {
typealias ResultType
func rawValue() -> ResultType
func printValue(r: ResultType)
}
protocol StringOutputItem: OutputItem {}
extension StringOutputItem {
typealias ResultType = String // without this typealias declaration, the program WILL compile since ResultType is inferred to be of type Int
func rawValue() -> Int {
return 123
}
func printValue(r: Int) {
...
}
}
struct Test: StringOutputItem {} // Error: Type 'Test' does not conform to protocol 'OutputItem'