Swift 协议扩展实现另一个具有共享关联类型的协议
Posted
技术标签:
【中文标题】Swift 协议扩展实现另一个具有共享关联类型的协议【英文标题】:Swift protocol extension implementing another protocol with shared associated type 【发布时间】:2015-11-28 05:35:54 【问题描述】:考虑以下几点:
protocol Foo
typealias A
func hello() -> A
protocol FooBar: Foo
func hi() -> A
extension FooBar
func hello() -> A
return hi()
class FooBarClass: FooBar
typealias A = String
func hi() -> String
return "hello world"
此代码编译。但是如果我注释掉关联类型typealias A = String
的显式定义,那么由于某种原因,swiftc 无法推断出类型。
我感觉这与共享相同关联类型但没有通过类型参数化等直接断言的两个协议有关(可能关联类型不够强大/不够成熟?) ,这使得类型推断变得模棱两可。
我不确定这是否是语言的错误/不成熟,或者我在 协议扩展 中遗漏了一些细微差别,这些细微差别理所当然地导致了这种行为。
有人能解释一下吗?
【问题讨论】:
当你说swift无法推断类型时,编译器错误是什么,在哪一行? @PatrickGoley Swift 看不到hello()
和 hi()
的返回类型 A
是等效类型,因此,需要我另外实现 hello()
方法。它说FooBarClass
不符合协议FooBar
我认为这应该被视为一个错误。我发现的解决方法是在FooBar
协议中声明typealias
。即:protocol FooBar: Foo typealias A; func hi() -> A
@rintaro 抱歉,在我发送答案之前我没有看到你的注释。
【参考方案1】:
看看这个例子
protocol Foo
typealias A
func hello() -> A
protocol FooBar: Foo
typealias B
func hi() -> B
extension FooBar
func hello() -> B
return hi()
class FooBarClass: FooBar
//typealias A = String
func hi() -> String
return "hello world"
使用泛型
class FooBarClass<T>: FooBar
var t: T?
func hi() -> T?
return t
let fbc: FooBarClass<Int> = FooBarClass()
fbc.t = 10
fbc.hello() // 10
fbc.hi() // 10
【讨论】:
值得一提的是,这是Swift编译器的一个bug,B
可以和A
同名。【参考方案2】:
为了符合所述协议,需要为协议中的关联类型提供显式值。这可以通过硬编码类型来完成,就像您对 typealias A = String
所做的那样,或者使用您提到的参数化类型,如下所示:
class FooBarClass<T>: FooBar
typealias A = T
...
Swift 不会从协议的已实现方法推断您的关联类型,因为多个方法的类型不匹配可能会产生歧义。这就是为什么必须在实现类中明确解析类型别名的原因。
【讨论】:
您能否详细说明“因为多种类型不匹配的方法可能存在歧义。”?以上是关于Swift 协议扩展实现另一个具有共享关联类型的协议的主要内容,如果未能解决你的问题,请参考以下文章