6

考虑以下:

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 无法推断出类型。

我感觉这与共享相同关联类型但没有通过例如类型参数化(可能关联类型不够强大/不够成熟?)的直接断言的两个协议有关,这使得类型推断模棱两可。

我不确定这是否是语言的错误/不成熟,或者我可能错过了协议扩展中的一些细微差别,这些细微差别理所当然地导致了这种行为。

有人可以对此有所了解吗?

4

2 回答 2

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
于 2015-11-28T19:37:04.593 回答
0

为了符合所述协议,需要为协议中的关联类型提供显式值。这可以通过硬编码类型来完成,就像你已经完成的那样typealias A = String,或者使用你提到的参数化类型,如下所示:

class FooBarClass<T>: FooBar {
    typealias A = T
    ...
}

Swift 不会从协议的已实现方法推断您的关联类型,因为多个方法的类型不匹配可能会产生歧义。这就是为什么必须在您的实现类中显式解析类型别名的原因。

于 2015-11-28T06:37:54.723 回答