Generics 重写的方法具有与基方法';不兼容的泛型签名;s的泛型签名

Generics 重写的方法具有与基方法';不兼容的泛型签名;s的泛型签名,generics,overriding,signature,swift5,xcode11.4,Generics,Overriding,Signature,Swift5,Xcode11.4,我刚刚更新到Xcode 11.4。 我收到以下错误: Overridden method 'equals' has generic signature <T where T : Gradient> which is incompatible with base method's generic signature <T where T : Fill>; expected generic signature to be <T where T : Fill> 重

我刚刚更新到Xcode 11.4。 我收到以下错误:

Overridden method 'equals' has generic signature <T where T : Gradient> which is incompatible with base method's generic signature <T where T : Fill>; expected generic signature to be <T where T : Fill>
重写的方法“equals”具有与基方法的泛型签名不兼容的泛型签名;预期通用签名为

类填充:可均衡{
func等于(其他:T)->Bool其中T:Fill{}
}
func==(左:T,右:T)->Bool其中T:Fill{
返回左侧等于(其他:右侧)
}
等级梯度:填充{
重写func equals(other:T)->Bool其中T:Gradient{}
}
这是如何改变的?

请查看此线程


此编译错误可防止将来发生崩溃

在我的例子中,我只是通过以下方法修复此错误:-

override func equals<T>(other: T) -> Bool where T: Fill {
    guard let other = other as? Gradient else { 
        return false 
    }
    ...
}
override func equals(其他:T)->Bool其中T:Fill{
guard let other=其他as?梯度else{
返回错误
}
...
}

但是金刚鹦鹉也有一些类似的错误,所以只要用你的错误问题替换梯度就可以了。

你不能像那样改变约束的原因是这样做会违反Liskov替换原则。编译器从未检查过重写函数的通用签名,这导致了各种运行时崩溃,因此我在Swift 5.2编译器中实现了此错误

让我们看一下您自己的示例,以了解问题所在。可以编写以下代码:

let fill1:Fill=Fill()
设fill2:Fill=Gradient()
设isEqual=fill2.equals(其他:fill1)
这是不正确的,因为
Gradient.equals(other:)
需要
other
Gradient
继承。但是,由于
fill2
有一个静态类型
Fill
,因此我可以绕过该约束并传递一个类型为
Fill
的值

如果
Gradient.equals(other:)
尝试访问
other
上仅存在于
Gradient
实例上的属性或函数,则代码将在运行时崩溃,因为该属性或函数在
Fill
上不可用:

类填充:可均衡{
func equals(other:T)->Bool其中T:Fill{…}
}
等级梯度:填充{
私有(集合)变量id:String=UUID().uuistring
覆盖func equals(其他:T)->Bool,其中T:Gradient{
如果'other'是'Fill'类型的值,则返回id==other.id//崩溃`
}
}
因此,编译器现在禁止您在重写函数时添加不兼容的约束

现在,基本上有两种解决问题的方法-更改代码并避免在重写函数中添加不兼容的约束,或者使用
as?
type(of:)
在重写函数中执行运行时检查,以检查传递的值是否确实满足新约束,然后尝试使用它:

override func equals(其他:T)->Bool其中T:Gradient{
如果类型(of:other)=Fill.self{return false}
return id==other.id//OK
}

您是否阅读了发行说明?我相信他们对此非常清楚。
override func equals<T>(other: T) -> Bool where T: Fill {
    guard let other = other as? Gradient else { 
        return false 
    }
    ...
}