我对Swift很陌生,但我对OO编程有一些经验。我已经开始尝试在swift中使用参数化类,并且在重载方法时遇到了一个奇怪的设计特性。如果我定义以下类:
class ParameterClassA {
}
class ParameterClassB: ParameterClassA {
}
class WorkingClassA<T: ParameterClassA> {
func someFunction(param: T) -> Void {
}
}
class WorkingClassB: WorkingClassA<ParameterClassB> {
override func someFunction(param: ParameterClassA) {
}
}
然后代码就可以编译了。但是,正如您会注意到的,我已经重载了通常使用参数类型的函数,在我的示例中是
ParameterClassB
,并给它一个类型为ParameterClassA
的参数。这应该如何工作?我知道Java中不允许这样做,我想知道类型参数是如何被解释的。它可以是类型参数的类层次结构中的任何内容吗?另外,请注意,如果删除
: ParameterClassA
中的类型参数约束,则问题完全相同。如果我删除了
WorkingClassA
关键字,那么会得到一个编译器错误,请求添加它。谢谢你的解释!
最佳答案
它与泛型(您称之为“参数化”)毫无关系。它与一个函数类型如何在swift中替换另一个函数类型有关。规则是函数类型相对于其参数类型是反变的。
为了更清楚地看到这一点,它将有助于抛开所有误导性的一般性内容和重写性内容,而直接集中精力于用一种函数类型替换另一种函数类型的业务:
class A {}
class B:A {}
class C:B {}
func fA (x:A) {}
func fB (x:B) {}
func fC (x:C) {}
func f(_ fparam : B -> Void) {}
let result1 = f(fB) // ok
let result2 = f(fA) // ok!
// let result3 = f(fC) // not ok
我们期望传递给函数
f
作为其第一个参数a,函数类型为B -> Void
,但函数类型为A -> Void
是可接受的,其中a是b的超类。但是类型
C -> Void
的函数是不可接受的,其中c是b的子类。函数在其参数类型上是反变量的,而不是协变的。