我对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的子类。函数在其参数类型上是反变量的,而不是协变的。

10-07 19:42
查看更多