How to throw to superclass when subclass has override function

A superclass of Car is created and a subclass of Jaguar is created. The info () → Void function in the subclass redefined the superclass function. An instance was created with the name Auto of type Jaguar .

Problem:

I can't seem to give theAuto the Car type, see 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 did not quite understand the concept of casting along with a redefining script. Why can't I cast? Is overriding my top caste overriding?

Thank you very much for your help and time.

+5
source share
2 answers

Since you are overriding a method in a subclass, you get a dynamic dispatch. The method implementation for the call will be based on the dynamic type of the instance that it called. Upcasting a Jaguar to Car only changes the static type of the instance - the dynamic type is still Jaguar , for this type of instance created.

Therefore, the increase in speed has nothing to do with the dynamic dispatch of the method, nor should it, since the whole point of the dynamic dispatch should ensure that the correct implementation of the method for this instance is called regardless of what it statically injects.

The type of behavior you expect is static dispatch — the compiler chooses the implementation to invoke based on the static type of the instance. This is usually achieved by overloading (rather than overriding) functions.

For example, the 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 decides which implementation of info(for:) call based on the static types of what it is called on and the arguments passed. If he either called Car , or the argument passed was statically entered as Car , congestion can only be sent to Car .

Another example of static sending is protocol extension, where the method is not a protocol requirement (since this requirement requires dynamic sending).

 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 permits which implementation of info() is called solely on the basis of the static type of the instance that it called.

+4
source

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

Do you have 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 car is Jaguar
Do you have jaguar

Only the first section is printed. The second car must not be thrown at the Jaguar, because it is a BMW.

+1
source

Source: https://habr.com/ru/post/1266163/


All Articles