A generic class parameter in a C++ template can be straightforwardly translated into Java by turning it into a parameter of type Object, the root of the Java class hierarchy. However this translation is only approximate since the Java class types are reference types [18] as explained below.
template <class T>
class Ccpp {
private: T t;
public:
Ccpp (T x) { t = x; }
T f(T x) { return t; }
}
and a first approximation to it in Java:
class Cjava {
private Object t;
public Cjava (Object x) {
t = x;
}
public Object f(Object x) {
return t;
}
public static void main (String[] args) {
Integer io = new Integer(5);
Cjava c = new Cjava(io);
Integer jo = (Integer) c.f(io);
}
}
In the above Java translation, the method f is not restricted to Integer argument. To impose the necessary type constraint, one can use inheritance and redefinition. However, to override a parent method in a subclass CIntjava, Java requires that the signature of the overriding method be the same as that of the corresponding parent method. (Otherwise, the new definition is treated as a valid overload.) So extra type checking code is needed to preserve the behavior. Observe also that an instance of CIntjava can be assigned to a variable of type Cjava.
Even though the subclass has ``method-stubs'' of the order of the number of methods in the parent class, it does not require duplication of method bodies.
class CIntjava extends Cjava {
public CIntjava (Integer x) {
super(x);
}
public Object f(Object x) {
if (x instanceof Integer) {
return super.f(x);
} else return null; /* "Erroneous Call" */
}
}
This approach resembles homogeneous translation of Pizza's polymorphism into Java [29].
Alternatively, one can change the signature of the method f in CIntjava to accept and return only Integer objects. This can be accomplished using composition and forwarding. Unfortunately, all this can clutter up the code and introduce run-time overheads.
class CIntjava {
protected Cjava c;
public CIntjava (Integer x) {
c = new Cjava(x);
}
public Integer f(Integer x) {
return (Integer) c.f(x);
}
}
Observe that Java does not permit covariant typing of Eiffel [27] where a parent method can be overridden in the subclass using a method whose signature is more ``restrictive'' than the corresponding parent method. Observe also that Pizza's support for parameteric polymorphism improves readability, but has similar overheads due to translation into Java [29].
Refer to the Java utility classes such as java.util.Vector, java.util.Stack,
[4] java.util.Hashtable, etc for more
examples.