Wednesday, May 30, 2007

Comparisons of C++ and Java (IV): Accessibility of Indirect Base Classes

Firstly, let’s take a look at two examples in C++ and Java respectively:

Example 1 (In Java):

A.java
public class A {
A (){}
void printMsg(){
System.out.println("print from class A");
}
}

B.java
public class B extends A {
B (){}
void printMsg(){
System.out.println("print from class B ");
}
}

C.java
public class C extends B {
C (){}
void printMsg(){
// direct base class B is accessible but now indirect base class A
super.printMsg();
System.out.println("print from class C");
}
}

Test code snippet

C c = new C();
c.printMsg();

The inheritance path looks like:

A (indirect base)
|
B (direct base)
|
C

The test Results are:
print from class B
print from class C

In class C, method "printMsg()" in direct base class B is accessible by calling:

super.printMsg()

However, the method "printMsg()" in indirect base class A is not accessible. What about in C++? Let’s take a look at an exactly same example but in C++.

Example 2 (In C++): same as Example 1 but written in C++

class A:

class A{
public:
A(){}
void printMsg( ){
cout<<" print from class A "<<endl;
}
};

class B:

class B : public A{
public:
B(){}
void printMsg(){
cout<<" print from class B "<<endl;
}
};

class C:

class C:public B{
public:
C(){}
void printMsg(){
A::printMsg();//indirect base is accessible too
B::printMsg();
cout<<" print from class C "<<endl;
}
};

Test code snippet:

C* c = new Polygon::C();
c->printMsg();

The test code will print:
print from class A
print from class B
print from class C

As we have noticed, the indirect base class A is accessible in class C which is different than in Java as shown in Example 1.

Why C++ and Java are different at this point?

As my understanding it is because in C++, multiple-inheritance is allowed. A derived class may inherit methods with same finger print from different base classes as shown below:

class A
class A {
public A();
pulbic printMsg();
}

class B1
class B1 {
public B1()
pulbic printMsg();
}

class B2
class B2 {
public B2();
pulbic printMsg();
}

class C
class C : public B1,B2{
public C();
pulbic printMsg();
}


The inheritance path is shown as:
A (indirect base)
/ \
B1 B2 (direct base)
\ /
C

Class C has two direct base classes B1 and B2. This arises the ambiguity because both have a method called “printMsg()”. Image what if the printMsg() in class C would like to inherit both "printMsg()" from class B1 and class B2? Fortunately, C++ provides techniques to eliminates the ambiguities by explict qualification: B1::printMsg() or B2::printMsg() explicitly tells compiler which version of "printMsg()" is been used. However, the solution also leads the de-encapsulation of indirect base classes A in the inheritance tree.

Unlike C++, in Java, strict inheritance is enforced and all classes are single-rooted by the class Object. Multiple implementation inheritance is not allowed, thus the confusion in the examples above does not exist. Everything in the super class is inherited by the subclass. Thus, there is no need to access the indirect base class upward in the inheritance tree.

No comments: