gpt4 book ai didi

ios - 在 Swift 协议(protocol)上应用 self 约束与在协议(protocol)的扩展上应用 self 约束之间的区别

转载 作者:可可西里 更新时间:2023-11-01 01:59:36 25 4
gpt4 key购买 nike

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

class Foo {
let val: Int

init(_ val: Int) {
self.val = val
}
}

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

class Bar : Foo, IFooComparer {
func compareTo(other: Foo) -> Bool? {
guard let otherBar = other as? Bar else { return nil }

return self.val < otherBar.val
}
}

let foos: [Foo] = [
Foo(1),
Bar(2),
]
let newFoo = Bar(3)
for foo in foos {
if let comparer = foo as? IFooComparer, let result = comparer.compareTo(other: newFoo) {
print("\(foo.val): \(result)")
} else {
print("\(foo.val): Cannot compare")
}
}

代码将在第一次循环迭代中成功,然后在第二次循环迭代中失败,并抛出 EXC_BAD_ACCESS。从我在调试器中收集到的信息来看,在调用 compareTo() 之前,在循环体内创建的作用域变量“comparer”似乎是一个有效对象;但在 compareTo() 内部,“self”变量看起来像是一个损坏/解除分配的对象,这会导致异常。现在奇怪的是,如果我将协议(protocol)定义更改为:

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

代码将运行良好。有人可以帮我解释一下差异吗?谢谢!P.S: 我正在运行 Xcode 版本 9.2 (9C40b)

最佳答案

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

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

所以我们有这样的工作方法:

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
}
}

现在,如果我们使用这个方法而不是常规的compare,我们将有

if let comparer = foo as? IFooComparer,
let result = comparer.compareTo2(other: newFoo)

这也行不通,因为

'IFooComparer' is not a subtype of 'Foo'

这告诉我编译器在解析扩展的约束时遇到问题。

当您直接向协议(protocol)本身指定约束时,也会发生同样的情况。

对此的一个解决方案是转换为实现协议(protocol)的具体类,即 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) {
...

基于此,我认为问题是在某些情况下编译器无法验证协议(protocol)/扩展约束。这与您对协议(protocol)本身设置约束无关。

虽然我很想听到对此的准确解释,但我不确定为什么它不能解决约束。

关于ios - 在 Swift 协议(protocol)上应用 self 约束与在协议(protocol)的扩展上应用 self 约束之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47665534/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com