gpt4 book ai didi

swift - 难以理解 Swift 协议(protocol)扩展中的 `Associated Types`

转载 作者:行者123 更新时间:2023-11-28 08:55:56 25 4
gpt4 key购买 nike

我正在努力理解 swift 中的协议(protocol)和协议(protocol)扩展。

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

// 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.ResultType 中删除 Self,我会收到错误消息 'ResultType' is ambiguous for type lookup in this context

我如何向协议(protocol)扩展发送信号以将哪种类型用于 ResultType

我的目标是能够将协议(protocol)及其扩展应用到类中,如下所示:

// 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

如果我完全不了解协议(protocol)扩展如何提供默认实现,我对如何实现相同的结果持开放态度。

最佳答案

Swift 编译器通过实现的协议(protocol)方法的类型签名推断ResultType 的类型。例如,在下面的 StringOutputItem 声明中,编译器知道 StringOutputItemResultTypeString 类型,即使没有明确声明:

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协议(protocol)并使用正确的类型实现它。

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

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)的方法时使用正确的类型。

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 - 难以理解 Swift 协议(protocol)扩展中的 `Associated Types`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33060472/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com