Ios 在Swift协议上应用自约束与在协议扩展上应用自约束的区别

Ios 在Swift协议上应用自约束与在协议扩展上应用自约束的区别,ios,swift,Ios,Swift,当我将自约束应用于协议本身时,我遇到了一个奇怪的运行时错误,而当我将约束更改为协议的扩展时,代码按预期运行。我想知道是否有人能帮我解释这种差异,或者帮我确认这是意外行为(即语言错误)。 以下是不起作用的代码(它是在Playway中编写的,因此主逻辑不在方法中): 代码将正常运行。有人能帮我解释一下区别吗?谢谢 附言:我正在运行Xcode 9.2版(9C40b)这种“有效”的方法实际上并不是在做同样的事情。它不再需要解析约束,因为方法是在协议中声明的,而不是在扩展中声明的 使用此逻辑,让我们向该扩

当我将自约束应用于协议本身时,我遇到了一个奇怪的运行时错误,而当我将约束更改为协议的扩展时,代码按预期运行。我想知道是否有人能帮我解释这种差异,或者帮我确认这是意外行为(即语言错误)。 以下是不起作用的代码(它是在Playway中编写的,因此主逻辑不在方法中):

代码将正常运行。有人能帮我解释一下区别吗?谢谢 附言:我正在运行Xcode 9.2版(9C40b)

这种“有效”的方法实际上并不是在做同样的事情。它不再需要解析约束,因为方法是在协议中声明的,而不是在扩展中声明的

使用此逻辑,让我们向该扩展添加一个方法,并尝试查看它是否可以通过这种方式解决约束

因此,我们有这种工作方法:

protocol IFooComparer {
    func compareTo(other: Foo) -> Bool?
}
extension IFooComparer where Self: Foo { }
让扩展添加一个新方法,
compare2

extension IFooComparer where Self: Foo {
    func compareTo2(other: Foo) -> Bool? {
        return nil
    }
}
现在,如果我们使用此方法而不是常规的
比较
,我们将

if let comparer = foo as? IFooComparer,
   let result = comparer.compareTo2(other: newFoo)
这也不起作用,因为

“IFooComparer”不是“Foo”的子类型

这说明编译器在从扩展解析约束时遇到问题

当您直接将约束指定给协议本身时,也会发生同样的情况

解决此问题的一个方法是强制转换到实现协议的具体类,即
Bar

protocol IFooComparer where Self: Foo {
    func compareTo(other: Foo) -> Bool?
}

for foo in foos {
    if let c = foo as? Bar, let result = c.compareTo(other: foo) {
    ...
基于此,我认为问题是在某些情况下编译器无法验证协议/扩展约束。这与您在协议本身上设置约束无关


尽管如此,我还是很想听到一个精确的解释,我不确定为什么它不能解决这个限制。

谢谢你的见解!是的,您是对的,将约束移动到扩展基本上会释放约束,使其不再是实现类的要求。事实上,如果约束在扩展上,那么定义一个不从Foo继承但仍然实现IFooComparer协议的新类是没有问题的,如果约束在协议本身上,这是不可能的。我可以确认这个问题在最新版本的Xcode/Swift中仍然存在。
if let comparer = foo as? IFooComparer,
   let result = comparer.compareTo2(other: newFoo)
protocol IFooComparer where Self: Foo {
    func compareTo(other: Foo) -> Bool?
}

for foo in foos {
    if let c = foo as? Bar, let result = c.compareTo(other: foo) {
    ...