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.