“Late self binding” and “static super binding”

Today in my course of object oriented programming languages I ran into “late self binding”.

First of all we all know that when a class “Foo” is the super class for a class “Bar”, every method of Foo is callable from within the class “Bar”. This is the whole point of inheritance. So suppose we have the following:

public class A {
	public void printMsg1()
	{
		System.out.println("A>>msg1");
	}
}

public class B extends A {
	public void printMsg2()
	{
		System.out.println("B>>msg2");
		super.printMsg2();
	}
}

We know that when we have an instance of class A, and we call a.printMsg1() we know that we will get “A>>msg1” as output in the console. And if we call b.prinMsg2() we will get “B>>msg2” followed by “A>>msg1”. The second message comes from our class A, which is obviously the parent of our class B, i.e. the super class. Now let’s use a third class, C.

public class A {
    public void printMsg2()
    {
        System.out.println("A>>msg1");
    }
}
public class B extends A {
    public void printMsg1()
    {
        System.out.println("B>>msg2");
    }
}
public class C extends B {
    public void printMsg1()
    {
        System.out.println("C>>msg1");
        super.printMsg1();
    }
}

We can clearly see that our super class B does not have a method named printMsg1(), so what happens? The compiler will look at compile-time a level up in our inheritance tree and will find a method named like that in our class A and use that one. So the output of a call to an instance of class C it’s method c.printMsg1() will give us “C>>msg1” followed by “A>>msg1”. If we were to delete the printMsg1() procedure from class A and insert it in class B, everything would still work just fine because our call to super with find the method we are looking for in the class B, which it will check before class A, since it’s our direct parent.

This entire process is called static super binding. This means that at compile-time the compiler knows in which class it will have to look for a call to super.

Now comes the tricky part, late self binding.

public class A {
	public void printMsg1()
	{
		System.out.println("A>>msg1");
		this.printMsg2();
	}
	public void printMsg2()
	{
		System.out.println("A>>msg2");
	}
}

public class B extends A {
	public void printMsg1()
	{
		System.out.println("B>>msg1");
		super.printMsg1();
	}
	public void printMsg2()
	{
		System.out.println("B>>msg2");
	}
}

I don’t know about you guys, but I never fully grasped the usage of this.

On an instance of B, when we call b.printMsg1() we will get the output “B>>msg1” and then we call our super and ask it to execute printMsg1(). This will give us the output “A>>msg1”. Then we call this and ask it to execute printMsg2().

The actual this is the calling class instance. This is obviously our instance of B. So this does not point to the current enclosing class (A), but to the enclosing class that initially called the first method on the bottom of our call stack. In our case this is b.printMsg1(). If we look in our class B we will see that we indeed have a method named b.printMsg2(). So we get the output “B>>msg2”.

So what happens if we don’t have that method (b.printMsg1()) in our child class? Simple. If you consider the line this.printMsg2() as a call to our initial caller, the B class, you know that in case the method is not present we will look for it in the super class.

Why the name late self binding then? Well, this stems from the fact that at compile-time you don’t know which method of which class will be at the beginning of the call stack. So therefore the compiler cannot tell then which method from which class needs to be invoked.

The super can always be determined at compile-time. This is because a class has a unique super (with multiple inheritance this is no longer true) and can therefore be identified. The reason for this is that you can not change your super class at run-time. Say a class B extending class A can never be modified during run-time to extend class C instead of class A.

Hope this helps somebody,

Christophe

PS: I know that I’ve used some terminology that might be incorrect, but I do think the concept is clear and outlined correctly. If you have any remarks I’d be glad to hear them in the comments.

Advertisements