Swift,我可以用更具体的派生参数类型重写方法吗

Swift, can I override a method with a more specific derived parameter type

PlayingCard 继承自 Card

给定两个同名函数:

 func match(othercards : [PlayingCard]) ->  Int {
     return 2 
 }

 func match(othercards : [Card]) ->  Int {
     return 2 
 }

它抛出错误提示:使用选择器 'match:' 的覆盖方法具有不兼容的类型 '([PlayingCard]) -> Int'

为什么???它的两个函数名称相同但参数类型不同,为什么它仍然要求覆盖??如果我这样做,那么即使那样也被称为错误

由于 PlaingCard 继承自 Card,因此您不能以这种方式重写该方法。

考虑一下如果您尝试使用 PlayingCard 的实例调用 match 会发生什么。它会调用这两种方法中的哪一种?这将是模棱两可的,因此是不允许的。

在这种情况下,一种解决方案是更改采用更具体类型的方法的名称。例如

 func matchPlayingCard(othercards : [PlayingCard]) ->  Int {
     return 2 
 }

Swift 编译器必须将 PlayingCardCard 视为同一类型。如果有人继承(通过子类型或协议(在某些情况下)),那可以解释它。

尽管它可能被认为是 code smell, you can also check the type at runtime, and use only one function, as in the accepted answer here: Checking if an object is a given type in Swift

类似示例的解释中给出了一些可以应用的模式——尽管问题是关于 C# 的,但可以应用类似的面向对象技术:overriding method with derived parameter instead of base

你能做到吗?

class Card {
    func match(othercards : [Card]) ->  Int {
        return 2 // I changed the return value just to test it
    }
}

class PlayingCard : Card {
    func match(othercards : [PlayingCard]) ->  Int {
        return 1
    }
}

是!

具体来说,如果 Card 没有扩展 NSObject

class Card {
    func match(othercards : [Card]) ->  Int {
        return 2 // I changed the return value just to test it
    }
}

另一方面,如果 Card 扩展 NSObject

class Card : NSObject {
    func match(othercards : [Card]) ->  Int {
        return 2 // I changed the return value just to test it
    }
}

然后你得到错误!

看起来 overloading 只适用于 "pure" Swift 类.