I’m trying to understand some of the nuances of inheritance but I can’t find an answer to this question. Consider the following:
class SuperClass {
method foo {
print "in SuperClass.foo"
}
method bar {
print "in SuperClass.bar"
foo();
}
}
class SubClass inherits SuperClass {
method foo {
print "in SubClass.foo"
}
}
SubClass a = SubClass.new()
a.bar()
Is the output this:
in SuperClass.bar
in SuperClass.foo
Or this:
in SuperClass.bar
in SubClass.foo
4
It depends on the language you are using (and sometimes on how the methods are declared).
There are essentially two ways for the implementation to perform method calls: static dispatch and dynamic dispatch.
In static dispatch, the compiler determines at compile time exactly which method to call, without taking the possibility into account that there might be a sub-class that overrides the method.
With static dispatch, the output would be
In SuperClass.bar
In SuperClass.foo
In dynamic dispatch, the compiler does take it into account that a sub-class might override the method, so it sets thing up that the runtime environment can call the right method in either the super class or the sub class.
With dynamic dispatch, the output would be
In SuperClass.bar
In SubClass.foo
Which method of dispatch gets used depends on the language you use, how the methods are declared and how you perform the call.
In C++ and C#, the compiler uses static dispatch by default, unless the method was declared as virtual
.
In Java, the compiler uses dynamic dispatch by default.
2
Even when the method call originates in the superclass, it should call the overriding method in the subclass. This behaviour is sometimes called “open recursion”, and this feature is crucial for techniques like the “strategy pattern”. Open recursion is generally considered to be a fundamental concept of object-oriented programming, although it is not without problems.
There are some caveats as some languages add special requirements.
-
In some languages, you always have to invoke methods with the dot-notation for this to work. You’d have to say
this.foo()
rather than justfoo()
. -
Some languages require you to explicitly mark methods as overrideable. E.g. C++ would require the
foo
method to be markedvirtual
for this to work as expected. In most languages, methods can be overridden by default.
4
It depends. In some languages, the superclass foo () would be called by default, but there is a way to declare that you want the subclass version to be called instead (in c++ and c# you use the “virtual” keyword in the declaration of superclass.foo() to achieve this). In others (e.g. Java and most dynamic languages like ruby, python and so on) the subclass version is always used.
2