swift - 关联类型符合 Swift 中的泛型类的问题

标签 swift swift-protocols associated-types

我想定义一个具有关联类型的协议(protocol),该类型必须是特定基类的子类。明确地说,假设我有类似以下示例的内容。

class C<T> {
    init(arg: T) {}
}

class SC<T>: C<T> {}

protocol P {
    associatedtype A: C<Self>
    func foo(_ x: A)
}

struct D: P {
    typealias A = C<D>
    func foo(_ x: A) {}
}

struct E: P {
    typealias A = SC<E>
    func foo(_ x: A) {}
}

我希望这段代码能够正确编译。相反,我收到错误 Type 'D' does not conform to protocol 'P'Type 'E' does not conform to protocol 'P' . Xcode 还提供以下消息:Possibly intended match 'D.A' (aka 'C<D>') does not inherit from 'C<Self>'Possibly intended match 'E.A' (aka 'SC<E>') does not inherit from 'C<Self>' .

这些错误对我来说没有意义。在第一种情况下,C<D>应与 C<Self> 的类型相同所以C<D>应符合 C<D> == C<Self> .在第二种情况下,C<Self>应该是 C<E>所以 SC<E>应符合 C<E> == C<Self> .根据 Xcode 的消息,这些显然不是这种情况。

这是错误消息的编译器错误/问题,还是我误解了关联类型在这种情况下的工作方式?

最佳答案

我不认为这对您对关联类型的理解有问题,就像对泛型的理解一样。泛型不是协变的;参数化类型没有替换原则。换句话说,仅仅因为你可以在心理上插入 D代替 Self并不意味着您可以替代 C<D>对于 C<Self> .它们是不同的类型(不相关)。

这里有一个简单的反例来说明我的意思:

class C<T> {
    init(arg: T) {}
}
class Cat {}
class Kitten : Cat {}

现在让我们尝试使用 C<Kitten>其中一个 C<Cat>预计:

var c1 = C(arg:Cat())
var c2 = C(arg:Kitten())
c1 = c2 // error

我怀疑那个是您认为应该起作用的。它没有。出于同样的原因,您认为“C<D> 应该与 C<Self> 是同一类型”的看法是错误的。

为了使这与您的实际示例更相关,请考虑这个微不足道的案例。这编译:

class C<T> {
    init(arg: T) {}
}
protocol P {
    associatedtype A: C<Any>
    func foo(_ x: A)
}
struct D: P {
    func foo(_ x: C<Any>) {}
}

但这不编译:

class C<T> {
    init(arg: T) {}
}
protocol P {
    associatedtype A: C<Any>
    func foo(_ x: A)
}
struct D: P {
    func foo(_ x: C<String>) {}
}

嗯,String 是 Any,你可能会说,那为什么不能编译呢?这是因为这个事实无关紧要;泛型中的参数化类型没有替换原则。

关于swift - 关联类型符合 Swift 中的泛型类的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55602733/

相关文章:

ios - 用两个 CGPoints SpriteKit Swift 创建一条线

Swift协议(protocol)继承同名协议(protocol)方法

ios - UIViewController 中的多个初始化步骤问题(不能使用多重继承)

swift - 在泛型函数 where 子句中使用 Self 时出错

swift - NSTimer 不会调用私有(private)函数作为选择器

ios - 尽管表不为空,核心数据获取仍返回零记录

ios - Mapbox iOS : User location not showing after turning device location service on

generics - 类型参数与 std::ops::BitXor 输出关联类型之间的类型不匹配

rust - 如何消除关联类型的歧义?

ios - swift 3 : Cannot invoke (protocol method) with argument list of type (generic)