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.

Saturday, July 7, 2007

Comparisons of C++ and Java (VI): Constant Modifier

Constant modifier is const in C++ and final in Java. However, const and final are not equivalent at any situations (In C++, we can also define a constant by using the #define preprocessor directive, but I am not going to discuss it here)


1. For primitive data type,
const and final have the same meaning, that is the variable can only be assigned once and its value cannot be changed. For instance:


const int i = 10;

in C++ is equivalent to


final int i = 10;

in Java. It illegal to modify the variable after its initialization in both cases.


2. However,
for non-primitive data type (reference data type in Java, structured data types and address types in C++), const and final are different.

Let take a look at some examples. In Java, this piece of code is perfectly legal:


final int[] ary = {1, 2, 3, 4, 5};
ary[4] = 6; //legal

However in C++, this piece of code:


const int ary[] = {1, 2, 3, 4, 5};
ary[4] = 6; // illegal. compilation-time error

will generate compilation-time error:

Error: assignment of read-only location.


3. Why const and final are different regarding to non-primitive datatype?

For mathematics, a constant is a value that never changes, thereby remaining a fixed value. So in C++, a constant is a REAL constant. const is infectious. A const modifier ensures that the object is immutable (It is called Const Correctness in C++). When const keyword is involved when used with pointers or references, we can't modify what the pointer points to or the reference refers to.

While, there is no such const correctness in Java. A final modifier just tells the compiler that the reference to the object cannot be re-assigned, but nothing about its content. A final modifier can never change the immutability of an object. A constant in Java is NOT a real constant. const is a reserved keyword in Java. We may expect the implementation of Const Correctness in Java in the future.