Monday, July 30, 2007

Comparisons of C++ and Java (VII): An Example of Desirable Data Hiding

In many of my readings, data hidings are said undesirable and are not encouraged. However, I at some circumstance, data hidings can make things simpler. For example, in my work, I need to implement an application with classes relationship looks like:


A
/ \
C B
/ | \
B1 B2 B3


Class A is the base class, class B and C are subclasses of A, and class B1, B2 and B3 are subclasses of B. Base class A is defined as:

A.h

class A{
public:
A(){}
static int id;
virtual void doSomething();
virtual int getId(){return ++id;}
};

A.cc

int A::id=0;
void A::doSomething(){
for (int k = 0; k<10; k++)
cout<<"id is : "<<getId()<<endl;
}



Here method doSomething simply print out ids. We want class B and C have their own id sequences, and all class B's share the same id sequences. That is both B and C classes' ids should start from 1. Class B1, B2, and B3 will share the same id sequence. To achieve this, We can design class C and B as following:

B.h

class B:public A{
public:
B(){}
static int id;
virtual int getId()
{
return ++id;
}

B.cc
int B::id=0;


Since data member id is defined again in both class C and B, A/id is hidden and inaccessible from both classes. Each class holds their own data id which starts from 0;

For class B's subclasses, we want them to share the same id sequence, so we DO NOT want to hide the id from class B. class B1, B2 and B3 are defined as following:

B1.h

class B1:public B{
public:
B1(){}
};

B2.h

class B2:public B{
public:
B2(){}
};

B3.h

class B3:public B{
public:
B3(){}
};


And the following test code generate some results that is what we expect:


C* c = new C();
B1* b1 = new B1();
B2* b2 = new B2();
B3* b3 = new B3();

cout<<"In class C, ids are: "<<endl;
c->doSomething();
cout<<"In class B1, ids are:"<<endl;
b1->doSomething();
cout<<"In class B2, ids are: "<<endl;
b2->doSomething();


The result looks like:


In class C, ids are:
id is : 1
id is : 2
id is : 3
id is : 4
id is : 5
id is : 6
id is : 7
id is : 8
id is : 9
id is : 10
In class B1, ids are:
id is : 1
id is : 2
id is : 3
id is : 4
id is : 5
id is : 6
id is : 7
id is : 8
id is : 9
id is : 10
In class B2, ids are:
id is : 11
id is : 12
id is : 13
id is : 14
id is : 15
id is : 16
id is : 17
id is : 18
id is : 19
id is : 20
In class B3, ids are:
id is : 21
id is : 22
id is : 23
id is : 24
id is : 25
id is : 26
id is : 27
id is : 28
id is : 29
id is : 30


There may be many other ways to achieve the same goal, but I found this solution is so simple and easy to understand and implement.


In Java, we can do the exactly same thing except a little change in the syntax. I am not going to bother to write the code.


In both Java and C++, the mechanism of data hiding from inheritance is called implicitly data hiding. In C#, it is said we can do explicitly data hiding by using "new" modifier. I think it is a cool feature in the language because I can tell the compiler I am doing data hiding on purpose.

No comments: