i got a question regarding sheet 10 exercise 3.: Inheritance Hierarchy, at the last part it ask for the result of ad.foo(cd) which the solution said to be C.foo(B). why is that? my answer is D.foo(C) since the method is from D and argument would take its static type of C. is my understanding wrong?
ad.foo(cd) => C.foo(B) (from solution), my answer is D.foo(C)
from this i got that we have a static type c for the argument and using the dynamic type d for the method (by that i mean we look up a method foo which have type c in class d).
so i got another approach to it and hopefully its right.
first we got that ad have a static type A so we start from there and since cd have a static type C, we check in a which of its method have a parameter that C extends to and as close as possible ( C <= B, therefore A.foo(B) ). but since b is overwritten in class c we got C.foo(B) instead.
I guess in your first approach you missed that overloading is resolved at compile-time, so only signatures from A are available, even though the dynamic type is D.
This may seem unintuitive at first, but imagine a piece of code where the dynamic Type could vary (for example, by using a random number to decide what object to create). Now, if the compiler were to pick foo(C), but we actually created an instance of A, we would have a problem.
Hence, only the signatures from the static type can be used, as they are the only ones that are guaranteed to be available.
(I hope you don’t mind this extra explanation. I personally find that knowing why something is the case makes it much easier to remember)
well so in compiling time, we will use the static type in this situation C, I will check if D override a function that accept argument of type A that exist in C if yes I use it no I use the one in C argument if argument type cover the argument type I’m giving, but I think I understrand why now, so C is extanding B which have a foo(A a), so in our case D is overriding foo(A a) from B that got inherited by C. that’s why we are allowed to use override foo(A a ) in D.
Exactly. Remember that on a child class, all the methods inherited from the parent class are available. You can override them with a new definition, but if you do not, you inherit the implementation from the parent.
Thus, in the class C, there are the following methods:
foo(A), inherited from B, which overrides the original method from A
foo(B), defined in C, overriding the original method from A
foo(C), inherited from B
In D, we have
foo(A), defined in D, overriding the one from B, which overrides the original method from A
foo(B), inherited from C, overriding the original method from A
foo(C), defined in D, overriding the original from B`
Thus, you find the call to foo(A), which is available on C (even though it’s not written), and then at runtime you have an instance of D where the method foo(A) is overridden.