SwifT:获取通用协议作为参数的通用函数不起作用
SwifT: Generic function that gets generic protocol as parameter not working
假设我有这个简单的通用协议
protocol FooProtocol {
associatedtype Element: CustomStringConvertible
func echo(element: Element) -> Element
}
以及实现它的这个简单的通用结构
struct FooStruct<Element: CustomStringConvertible>: FooProtocol {
func echo(element: Element) -> Element {
return element
}
}
最后,我有以下功能:
func callEcho<T: FooProtocol>(container: T) {
container.echo(element: "some string")
}
这导致 error: cannot invoke 'echo' with an argument list of type '(element: String)'
解决办法是把函数改成
func callEcho<T: FooProtocol>(container: T) where T.Element == String {
container.echo(element: "some string")
}
我的问题是:为什么需要 where T.Element == String
约束?编译器知道 T
是实现 FooProtocol
的某个实体,协议只要求 Element
实现 CustomStringConvertible
,而我的字符串文字就是这样做的。那么为什么没有约束它就不能工作呢?
谢谢!
我不确定你为什么说 "the protocol only demands that Element implements CustomStringConvertible." 协议要求 echo
接受和 return its 元素,这可能或可能不是字符串。例如,我可以实现这个符合类型:
struct AnotherFoo: FooProtocol {
func echo(element: Int) -> Int { fatalError() }
}
那么如果我调用:
会发生什么
callEcho(container: AnotherFoo())
这会尝试将字符串文字传递给需要 Int 的函数。
container
的类型为 T
,因此 container.echo(element:)
需要一个类型为 T.Element
的参数——而这不一定是字符串。
如果打算将字符串文字传递给方法,则 T.Element
必须采用 ExpressibleByStringLiteral
,而不是 CustomStringConvertible
:
protocol FooProtocol {
associatedtype Element: ExpressibleByStringLiteral
func echo(element: Element) -> Element
}
现在编译:
func callEcho<T: FooProtocol>(container: T) {
_ = container.echo(element: "some string")
}
假设我有这个简单的通用协议
protocol FooProtocol {
associatedtype Element: CustomStringConvertible
func echo(element: Element) -> Element
}
以及实现它的这个简单的通用结构
struct FooStruct<Element: CustomStringConvertible>: FooProtocol {
func echo(element: Element) -> Element {
return element
}
}
最后,我有以下功能:
func callEcho<T: FooProtocol>(container: T) {
container.echo(element: "some string")
}
这导致 error: cannot invoke 'echo' with an argument list of type '(element: String)'
解决办法是把函数改成
func callEcho<T: FooProtocol>(container: T) where T.Element == String {
container.echo(element: "some string")
}
我的问题是:为什么需要 where T.Element == String
约束?编译器知道 T
是实现 FooProtocol
的某个实体,协议只要求 Element
实现 CustomStringConvertible
,而我的字符串文字就是这样做的。那么为什么没有约束它就不能工作呢?
谢谢!
我不确定你为什么说 "the protocol only demands that Element implements CustomStringConvertible." 协议要求 echo
接受和 return its 元素,这可能或可能不是字符串。例如,我可以实现这个符合类型:
struct AnotherFoo: FooProtocol {
func echo(element: Int) -> Int { fatalError() }
}
那么如果我调用:
会发生什么callEcho(container: AnotherFoo())
这会尝试将字符串文字传递给需要 Int 的函数。
container
的类型为 T
,因此 container.echo(element:)
需要一个类型为 T.Element
的参数——而这不一定是字符串。
如果打算将字符串文字传递给方法,则 T.Element
必须采用 ExpressibleByStringLiteral
,而不是 CustomStringConvertible
:
protocol FooProtocol {
associatedtype Element: ExpressibleByStringLiteral
func echo(element: Element) -> Element
}
现在编译:
func callEcho<T: FooProtocol>(container: T) {
_ = container.echo(element: "some string")
}