当子类中有覆盖函数时如何转换为超类

时间:2017-03-31 10:22:34

标签: swift class types casting

创建了超级 Car 和子类 Jaguar 。功能 info() - >子类中的Void 覆盖了超类的功能。已创建名为 theAuto Jaguar 实例。

问题:

似乎我无法将 theAuto 投射到汽车的类型,请参阅代码段及其评论

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

问题:

我认为我并没有完全理解与覆盖场景一起投射的概念。为什么我不能进行投射?覆盖动作是否限制了我的上部演员?

非常感谢你的帮助和时间

2 个答案:

答案 0 :(得分:4)

因为你覆盖子类中的方法,所以你得到动态分派。要调用的方法实现将基于它被调用的实例的动态类型。将Jaguar上传到Car只会更改实例的静态类型 - 动态类型仍为Jaguar,因为这是您创建的实例类型

因此,上传对动态调度方法没有任何影响 - 也不应该这样,因为动态调度的重点是确保给定实例的正确方法实现被称为,无论它被静态输入的内容。

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

例如,重载的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的重载静态分派到。

静态分派的另一个例子是协议扩展,其中该方法不是协议要求(因为它要求动态分派)。

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()的哪个实现只能根据它被调用的实例的静态类型进行调用。

答案 1 :(得分:1)

theAuto始终为Jaguar。它也总是Car。但是,调用info()将始终返回最具体类型的实现,因此将始终打印

  

你有一辆美洲虎

关于演员:

let car1 : Car = Jaguar()
let car2 : Car = BMW()

if let automobile = car1 as? Jaguar {
    print ("The automobile is a Jaguar")
    car1.info()
}

if let automobile = car2 as? Jaguar {
    print ("The automobile is a Jaguar")
    car2.info()
}

打印

  

汽车是捷豹车   你有一辆美洲虎

仅打印第一部分。第二辆车不能投入捷豹,因为它是宝马。