创建了超级 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
问题:
我认为我并没有完全理解与覆盖场景一起投射的概念。为什么我不能进行投射?覆盖动作是否限制了我的上部演员?
非常感谢你的帮助和时间答案 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()
}
打印
汽车是捷豹车 你有一辆美洲虎
仅打印第一部分。第二辆车不能投入捷豹,因为它是宝马。