how to cast up to super class when there is an override function in the sub class

送分小仙女□ 提交于 2021-01-27 06:01:38

问题


A super-class Car and a sub-class Jaguar was created. The function info() -> Void in the sub-class overrided the super-class' function. A instance named theAuto of type Jaguar had been created.

Problem:

Seems I cannot up casts the theAuto to the type of Car, please see the code snippet and its comments

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

Question:

I think I didn't fully understand the concept of casting together with override scenario. Why I cannot make the up casting? Is the override action limited my upper casting?

many thanks for your help and time


回答1:


Because you're overriding the method in a subclass, you're getting dynamic dispatch. The method implementation to call will be based on the dynamic type of the instance that it's called on. Upcasting a Jaguar to a Car only changes the static type of the instance – the dynamic type is still a Jaguar, for that's the type of instance you created.

Therefore upcasting has no bearing whatsoever on the dynamic dispatch of a method – nor should it, as the whole point of dynamic dispatch is to ensure that the correct method implementation for the given instance is called no matter what it's statically typed as.

The kind of behaviour you're expecting is static dispatch – the compiler chooses the implementation to call based on the static type of the instance. This is commonly achieved by overloading (rather than overriding) functions.

For example, an overloaded static method:

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

Here, the compiler resolves which implementation of info(for:) to call based on the static types of what it's being called on and the arguments being passed. If it's either called on Car, or the argument passed is statically typed as a Car, only Car's overload can possibly be statically dispatched to.

Another example of static dispatch is with a protocol extension, where the method isn't a protocol requirement (as making it a requirement gives it dynamic 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

Here, the compiler resolves which implementation of info() to call solely based on the static type of the instance that it's called on.




回答2:


theAuto is always a Jaguar. It is also always a Car. However, calling info() will always return the implementation for the most specific type and so will always print

You've got a Jaguar


Regarding casting:

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()
}

prints

The automobile is a Jaguar
You've got a Jaguar

Only the first section prints. The second car cannot be cast to a Jaguar, because it is a BMW.



来源:https://stackoverflow.com/questions/43138320/how-to-cast-up-to-super-class-when-there-is-an-override-function-in-the-sub-clas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!