Thursday, May 29, 2008

Inheritance/polymorphism/static/dynamic binding

1. Which one of the methods defined in interface or class with the same name will be called?

A: There is no method in interface can be called. Only the actual implementation of that method in class, which implements the interface mentioned, can be called.

2. Can subclass override methods that are declared static in the superclass?

A: No!

Methods a Subclass Cannot Override A subclass cannot override methods that are declared final in the superclass (by definition, final methods cannot be overridden). If you attempt to override a final method, the compiler displays an error message similar to the following and refuses to compile the program:"
... "Also, a subclass cannot override methods that are declared static in the superclass. In other words, a subclass cannot override a class method. A subclass can hide a static method in the superclass by declaring a static method in the subclass with the same signature as the static method in the superclass. " Quotation from Overriding Methods of The Java Tutorial

When you should use this kind of "hide" technique?
Don't use it unless your boss gives you the assignment!!! Then you have no choice. Something legal does not mean it is recommended.
Copied from Sun's Code Conventions for the JavaTM Programming Language

Quote:

Avoid local declarations that hide declarations at higher levels. For example, do not declare the same variable name in an inner block:

An interesting example here:

class Base {
static void doThis() {
System.out.println("Base static doThis()");
}

void doThat() {
System.out.println("Base instance doThat()");
}
}

class Sub extends Base {
// This is static method defined in the Sub class
// which does not override the Base doThis()
// only hide it.
// proved in the Test.main()
static void doThis() {
System.out.println("Sub static doThis()");
}

// This is instance method defined in the Sub class
// which does override the Base doThat()
void doThat() {
System.out.println("Sub instance doThat()");
}
}

public class Test {
public static void main(String[] args) {
// base is an instance of Sub
Base base = new Sub();
// legal cast both at compile and run time
Sub sub = (Sub)base;

base.doThis(); //Base static doThis()
base.doThat(); //Sub instance doThat()

sub.doThis(); //Sub static doThis()
sub.doThat(); //Sub instance doThat()

//Think why, try to understand the following concepts
//static binding : bind at compile time
//Dynamic binding : bind at run time
}
}

3. If subclass overrides the methods in super class, can subclass call the super class method?

A: Yes, you can. However, that is the subclass it self's choice. Outsider does not have this choice. You can see it clearly from the following example.

class Sup
{
void m1()
{
System.out.println("m1 in super");
}
}

class Sub extends Sup{
void m1()
{
super.m1();
System.out.println("m1 in sub");
}
}

public class T{
public static void main(String arg[])
{
new Sub().m1();
}
}

4. What is hide(a variable or a static method) means in computer languages (such as Java)? Should we do that?

A: Hide basic is a scope issue, when we have the same name in a smaller/more local scope, the smaller scope one will hide the upper ones. Here is a real life example: If you call your daughter Oprah Winfrey, then in your home, or in your daughter's kindergarten, people talk about Oprah Winfrey will refer to your daughter. The popular talk show host Oprah Winfrey will be hidden, unless you refer her as talk show host Oprah Winfrey. This example tells you three things: 1) Hiding is a scope issue. 2) Hiding cannot be complete/absolute. 3) Hiding is not good practice, since it causes confusion.My suggestion is don't call your daughter Oprah Winfrey, or don't practice hiding in your Java or C# or ... programming.The followings are two Java programs to illustrate the hiding concepts.

// hiding a instanse variable
class A {
int i = 3;
void method1() {
// this i will hide the member i
// bad coding practice
int i =5;
System.out.println(i); //5

// however, it can still be accessed by using this.i
System.out.println(this.i); //3
}
}

// hiding a static method
class A {
static void method1() {
System.out.println("in class A's static method1");
}
}

class B extends A {
// this will hide the static method1 in class A
static void method1() {
System.out.println("in class B's static method1");
}

public static void main(String[] args) {
// since we are in class B's scope
// call method1 directory will refer to B's method1,
// A's method1 is hidden
method1(); //in class B's static method1

// However, we still can call A's method1 even in B's territory
A.method1(); //in class A's static method1
}
}

5. Why the call to xy.amethod() calls amethod() in X instead of amethod() in Y in the following code?

class X {
public static void jout(String s) {
System.out.println(s);
}
static void amethod() {
jout("In X, amethod()");
}
}
class Y extends X {
static void amethod() {
jout("In Y, amethod()");
}
}
class Z extends Y {
static void amethod() {
jout("In Z. amethod()");
}
}
public class Test
public static void main (String[] args) {
X xy = new Y();
X xz = new Z();
Y yz = new Z();

xy.amethod();
xz.amethod();
yz.amethod();
}
}

A:

All three amethod()s here are static methods. static method is Class method, which has nothing to do with your object instantiation, dynamic binding, or polymorphism, whatsoever. In other words, the 3 line of codexy.amethod();
xz.amethod();
yz.amethod();can be replaced by the following 3 lines without causing any changes:X.amethod();
X.amethod();
Y.amethod();Since compiler interprets them exactly like this. xy and xz are reference type of X. yz is reference type of Y.Just remember "static is not dynamic" probably will help some.

6. When base class calls a method, how could the run time knows to called the overridden method in the derived class? The object is not even constructed yet.

A: Why? From the language theory, it is called deferred binding or dynamic binding or binding at run time. Compiler leaves the decision to run time. To make the decision at run time, you don't need the object built first. The only thing you need to know is the type of the actual object. In Java, the Class (not class) objects are loaded to the memory when it is first used. The run time knows it before any instance is constructed. In C++, the class methods virtual table is there for the same purpose. As you probably know, in C++, method are default to static binding, only virtual methods are dynamically bound. In Java, methods are default to dynamic binding, unless they are declared as static, private, or final.

7. Does private method defined in base class participate polymorphism, if the derived class has a same name method?

A: No, private method defined in any class will never participate polymorphism.

If you want to confuse yourself, your boss, and your co-worker (and you might get fired for that too), and define same name private methods along the hierarchy, the compiler will treat them individually, as no relationship at all. If you call private method in your class, the method will be bound at compile time (not runtime).See the following example:

// Base.java
public class Base {
public static void main(String[] args) {
Sub sub = new Sub();
System.out.println(sub.g()); // 20, not -100
}

private int f() {
return 20;
}

protected int g() {
// statc bound with Base.f()
// compiler does not know any derived class has f() or not
// and does not care either
return f();
}
}

class Sub extends Base {
// f() here has nothing to do with Base.f()!!!
// In real world programming, never do this!!!
public int f() {
return -100;
}
}

8. What kind of Java methods does not participate polymorphism?

A: Polymorphism for Java method is always there except the following three situations: 1) The method is declared as final
2) The method is declared as private
3) The method is declared as static In those three cases, static binding will be performed by the compiler. Compiler does not have the knowledge, nor care about the method was, is, or will be overridden by none, one, or many subclass(es). The decision is made by the runtime, which is called dynamic binding. See next question, which discuss the same topic in a different angle.

9. What methods in Java is static bound? Please compare with c++ too.

A: static, private, final methods are static bound.

Those 3 methods does not participate polymorphism. In other words, they are not allowed to be overridden. In c++, virtual function can be overridden, others not.
virtual in C++ --> nothing in Java
nothing in C++ --> final in Java

10. Do we need an object reference to call a static method?

A: No, not quite. See the following example.

MyClass t = null;
// the following two are equivalent
t.aStaticMethod();//OK
MyClass .aStaticMethod();//perfect

It is the class type; it doesn't need a "reference variable ". You can use a object reference to call a static method, of course, provided it has the right type. However, you don't have to. The above example clearly said that. t is not referring to anything but null, but has a MyClass type. If you know the old procedural programming, static method is equivalent to that, except in Java, we have a class Class. In Java, we can write magnificent old procedural program without any OO concepts by using all static methods. (No object reference at all).

11. What is the calling order of constructors along the hierarchy, from child up, or from ancestor down?

A:The order is from child up. However, the super() is always implicitly or explicitly called as the first statement before any code in the child being executed. This might cause some confusion here. If you put a print statement in each of the constructor, the ancestor one will be output first. The following code will illustrate how it works.This is called LIFO, which one is called the first, will be finished the last. The child is called first, but it call its parent as the first statement, and the immediate parent will call its parent as the first statement too, and so on. Therefore the far ancestor, which is the Object will finish its constructor the first, then its immediate child, and so on. That is why the print statements will finish from the ancestor down. The calling stack is working this way. Last In, First Out (LIFO)

public class Child extends Parent {
public Child() {
// super() is implicitly called here
System.out.println("Child");
}
public static void main(String[] args) {
new Child();
}
}
class Parent extends GrantParent{
public Parent() {
// super is explicitly called here
super("Mother's parent");
System.out.println("Parent");
}
}
class GrantParent{
public GrantParent(String sWhosPrt) {
System.out.println("GrantParent: " + sWhosPrt);
}
}

// output
// GrantParent: Mother's parent
// Parent
// Child

12.What is the static, instance initialization, constructor header, and code execution order? Why the radius prints out as 0 instead of 1 in the following code?

//Ex from Bruce Eckel's Book "Thinking In Java"
abstract class Glyph {
abstract void draw();
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}
class RoundGlyph extends Glyph {
int radius = 1;
RoundGlyph(int r) {
radius = r;
System.out.println(
"RoundGlyph.RoundGlyph(), radius = " + radius);
}
void draw() {
System.out.println("RoundGlyph.draw(), radius = " + radius);
}
}
public class PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}
//Output is:
//Glyph() before draw()
//RoundGlyph.draw(), radius = 0
//Glyph() after draw()
//RoundGlyph.RoundGlyph(), radius=5

A:

The execution order is:

  1. static variable initialization and static block executes only once when the class is loaded to the memory by JVM.

  2. When constructor is called, the constructor header executes first before instance variable initialization and instance block execution.

  3. instance variable initialization and instance block execute.

  4. Code in the constructor executes.

This is exactly what happened in your example (except no static stuff). The RoundGlyph constructor header executes first, which implicitly called default constructor of Glyph super(). The radius has not initialized yet; the value is 0. Then the radius is initialized to 1. Then the code in the RoundGlyph() constructor executes and changed radius value to 5. This kind of hair splitting trick, we'd better not know it, or don't tell your boss you know it. I probably learned from Mughal and Rasmussen's book, which I gave away after the test. Today, I wrote a little code to prove that I remembered it right. I usually do not pay a lot of attention to what is going to be on the SCJP test like Marcus Green does, however, it is quite safe to say, questions like this will NOT be on your test.Warning: Don't try this at work!

13. Constructor or not constructor? Please explain why the output of the following code is null?

public class My {
String s;
public void My(){
s = "Constructor";
}
public void go() {
System.out.println(s);
}
public static void main(String args[]) {
My m = new My();
m.go();
}
}
//output : null

A:

public void My() is not a constructor. The default constructor is called. s is still null by default.Constructor is not supposed to have a return type, even a void type. If it has, then it is not a constructor, but a method, which happens to have the same name as the class name. This is a tricky question just for testing your Java knowledge. Using class name as your method name is not considered as good code practice at work!

14. Base b = new SubBase(); How the compiler/Runtime to resolve the addresses of methods calls, Fields?

// TestBinding.java
class Base {
String s = "string in Base";
void init(){
System.out.println("init() call in Base");

}
}
class SubBase extends Base{
String s = "string in SubBase";
void init(){
System.out.println("init() call in SubBase");

}
}

public class TestBinding {
public static void main(String[] args) {
Base b = new SubBase();

// static binding on instance fields
System.out.println(b.s); //string in Base

// dynamic binding on instance methods
b.init(); //init() call in SubBase
}
}

A:

The above example plus comments actually told everything you need to know.When a field of an object is accessed using a reference, it is the type of the reference declared, which determines, which variable will actually be accessed.
Static Binding -- Bind at compile time: The addressing of the field is determined at compile time.

When a method is invoked on an object using a reference, it is the class of the current object denoted by the reference, not the type of the reference that determines which method implementation will be executed.
Dynamic Binding -- Bind at run time: The addressing of the method is determined at run time.Notice to C++ programmer: In C++, only virtual methods (functions) are bound at run time. In Java, methods are default to dynamic binding, unless they are declared as static, private, or final.

15. If I remove the init() from the Base in the above question, I got a compile error: ""method init() not found class Base". Why?

A: It will make you understand dynamic binding or polymorphism much better. If you remove init() from Base class, you actually take init() out of the polymorphism between Base and SubBase class. Compiler only know b is refer to a Base class, which does not have the method init(), compile time error!!! The Java compiler does not know, nor care who, when, where, how some other class is going to extends the Base class, there are some different named methods defined in them. And one of them happens to be called init(). They are totally irrelevant to the Base class.Remember SubBase ISA Base. Compiler does not care which child/grandchild/grand grandchild down the hierarchy b is actually referring to, and which init() it should call. However, they all have an init() (polymorphism). It is a runtime decision. Dynamic Binding.Dynamic binding, or binding at runtime only for those methods defined in Base class, either inherited or overridden by the subclass. The override can be already happened now or will happen in the future, the compiler does not care.

16. Here is another tricky code example for you to cracking on! Cover up the explanation to see you can explain it or not.

class Base {
int x = 3;
public Base (){}
public void showx(){
System.out.println("In base, x = " + x);
}
}
class SubBase extends Base {
int x = 2;
public void showx() {
System.out.println("In SubBase, x = " + x);
}
}

public class BindingTest {

public static void main (String args[]){
Base b = new SubBase();
b.showx();
System.out.println("In Main, the (?) x = " + b.x);
}
}

// output
/*
In SubBase, x = 2
In Main, the (?) x = 3
*/

A: Danger: Do not try this at work!

1) In main(), b.x is bound at compile time, since b is declared as Base, x is 3.
2) In main(), b.showx() is bound at runtime, since b is actually a SubBase. the SubBase.showx() will be called.
3) In SubBase, call of x in method showx() is bound at the compile time, in class SubBase, x is 2. This is a typical tricky question, good for you cracking the concepts, but never write it on your job. You would be fired for that, no kidding!!!

3 comments:

Unknown said...

Nice programs, i learned a lot about static and dynamic binding.

Unknown said...

Was Very useful. Please keep posting similar articles

hitesh kumar said...

Real life example of polymorphism

Suppose you are in home at that time you behave like son or father if you are in mall at that time you behave like customer and if you are in school then behave like student.