swift - 当子类中有覆盖函数时如何转换为父类(super class)

标签 swift class types casting

创建了父类(super class) Car 和子类 Jaguar。子类中的函数 info() -> Void 覆盖了父类(super class)的函数。已创建类型为 Jaguar 的名为 theAuto 的实例。

问题:

似乎我无法将 theAuto 转换为 Car 类型,请查看代码片段及其注释

class Car {
        func info() {
                print("You've got a car")
        }
}

class Jaguar : Car {
       override func info() {
               print("You've got a Jaguar")
       }
}

let theAuto = Jaguar()
theAuto.info() // --> You've got a Jaguar
let auto = theAuto as Car // casting but seems not working 
auto.info() // --> You've got a Jaguar
print(type(of: auto)) // fail to casting

问题:

我想我没有完全理解与覆盖场景一起转换的概念。为什么我不能化妆?覆盖操作是否限制了我的上层类型转换?

非常感谢您的帮助和时间

最佳答案

因为您要覆盖子类中的方法,所以您将获得动态 分派(dispatch)。要调用的方法实现将基于调用它的实例的动态类型。将 Jaguar 升级为 Car 只会更改实例的 static 类型——动​​态类型仍然是 Jaguar ,因为这是您创建的实例类型。

因此,向上转型对方法的动态分配没有任何影响——也不应该,因为动态分配的全部要点是确保调用给定实例的正确方法实现无论如何 它的静态类型是什么。

您期望的行为类型是静态 分派(dispatch)——编译器根据实例的静态类型选择要调用的实现。这通常通过重载(而不是覆盖)函数来实现。

例如,一个重载的static方法:

class Car {
    static func info(for car: Car) {
        print("You've got a Car")
    }
}

class Jaguar : Car {
    static func info(for jaguar: Jaguar) {
        print("You've got a Jaguar")
    }
}

let jaguar = Jaguar()
Jaguar.info(for: jaguar) // You've got a Jaguar
Car.info(for: jaguar)    // You've got a Car

let car = jaguar as Car
Jaguar.info(for: car)    // You've got a Car

在这里,编译器根据调用对象的静态类型和传递的参数来决定要调用哪个 info(for:) 实现。如果它在 Car 上调用,或者传递的参数静态类型为 Car,则只有 Car 的重载可能被静态分派(dispatch)到.

静态分派(dispatch)的另一个示例是协议(protocol)扩展,其中该方法不是协议(protocol)要求(因为将其作为要求会赋予它动态分派(dispatch))。

protocol Car {}

extension Car {
    func info() {
        print("You've got a Car")
    }
}

class Jaguar : Car {
    func info() {
        print("You've got a Jaguar")
    }
}

let jaguar = Jaguar()
jaguar.info() // You've got a Jaguar

let car = jaguar as Car
car.info()    // You've got a Car

在这里,编译器仅根据调用它的实例的静态类型来决定调用 info() 的哪个实现。

关于swift - 当子类中有覆盖函数时如何转换为父类(super class),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43138320/

相关文章:

php - 查找 CSV 单元外壳

swift - 如何创建事件指示器 View ?

ios - 为什么无法识别的选择器发送到实例?

c++ - 为什么我们两次使用引用运算符?

Objective-C:什么是 [ClassName self];做?

c# - 将 Object[] 转换为 String[] 或 List<String> 的最佳方法

ios - Xcode 7.2.1 Swift 2.1.1 无法将类型 'Dictionary<_,_>' 的值分配给类型 'Dictionary'

ios - iPhone 上 Watch 应用上的 watchOS 应用图标为空白

powershell - 有没有更好的方法在 Powershell 中获取 ‘class’ 语义(定义自定义类型)?

scala - 寻找第二个匹配隐式