swift - 具有关联类型的协议(protocol)中的开放递归有多大限制?

标签 swift swift-protocols

我的 Swift 代码有问题。它无法被编译,因为 swift 在某些协议(protocol)中看不到关联的类型。我找到了重现该问题的最低限度,以下代码代表了它。

protocol Woman {
    associatedtype Husband: Man
             where Husband.Wife == Self
}

protocol Man {
    associatedtype Wife: Woman
             where Wife.Husband == Self
}

protocol CoolWoman: Woman //warning
   where Husband: CoolMan {
}

protocol CoolMan: Man
   where Wife: CoolWoman {

    associatedtype Bike: Harley
             where Bike.Owner == Self
}

protocol Harley {
    associatedtype Owner: CoolMan
             where Owner.Bike == Self
}

编译此代码后,我在行中出现以下警告,并用 \\warning 标记:

Redundant conformance constraint 'Self': 'Woman'

这看起来是错误的,因为删除 : Woman where Husband: CoolMan 会使代码无法编译,因此一致性约束并不是多余的。该警告使代码不清楚,但(呃好吧)这是可以容忍的。但下面的函数不可编译的事实不容忽视。

func partnerBike<She: CoolWoman>() -> She.Husband.Bike? { //error
    return nil
}

它提供编译错误:

'Husband' is not a member type of 'She'

但这并不是事实,“丈夫是符合酷女人的她的成员”。对我来说,某些处理似乎删除了在编译之前或编译时从代码中发出警告“冗余一致性约束”的约束。

我是否错过了有关 Swift 语法构造的协议(protocol)的某些内容?
或者这只是编译器的一个错误?
为什么我的代码无法编译?
如何做到可编译?

<小时/>

Xcode 11.3 (11C29)、Swift 5

最佳答案

编译器就在那里,你确实有冗余的一致性,问题是它只有一个地方可以删除重复项,但是正如你所注意到的,这会破坏其他东西。

该问题是由 Woman/Man 系列协议(protocol)之间的循环引用引起的,因为它们的关联类型受到限制。

Woman.Husband 符合 ManMan.Wife 符合 Women。现在,CoolMan 派生自 Man,这意味着 CoolMan.Wife 已经是一个 Women。指定 CoolMan.WifeCoolWoman,而 CoolWomenWomen 会导致 Women 从两个不同的路径满足要求,因此出现冗余编译器警告。

这有点类似于菱形继承(钻石问题),编译器无法选择要遵循的继承路径。

这里的解决方案是找到另一种不围绕这么多循环依赖的设计。与保留循环一样,您需要在某个地方打破引用链,而这个地方取决于您想要通过此设计实现的目标。

关于swift - 具有关联类型的协议(protocol)中的开放递归有多大限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59620879/

相关文章:

ios - 如何修复协议(protocol)只能用作通用约束,因为它具有自身或关联的类型要求错误

ios - 类型 'StorageReference' 的值没有成员 'data' ?

swift - 我如何使用类型(: someVar) as a proper Type in Swift?

swift - 在 Swift 中向现有协议(protocol)添加函数签名

swift - 如何在 Swift 中使用子定义覆盖父类扩展

ios - Whatsapp 消息布局 - 时间和消息在同一行

ios - 基于字符串数组 (Swift) 在 UITableView 中的 viewdidload 上选择单元格

javascript - 检查颜色是否接近

Swift:我可以返回实现公共(public)类并符合公共(public)协议(protocol)的私有(private)类型吗?

swift - 为什么协议(protocol)中的仅获取属性要求不能通过符合的属性来满足?