Object-oriented languages: comparison with Java
Although Objective CAML sprang from the functional world, it is necessary to
compare its object-oriented extension to an important representative of the
object-oriented languages. We pick the Java language which, while
similar from the point of view of its implementation, differs strongly in
its object model and its type system.
The Java language is an object-oriented language developed by the SUN
corporation. The main site for access to the language is the following:
Link
http://java.sun.com
Main characteristics
The Java language is a language with classes. Inheritance is simple and
allows redefinition or overloading of inherited methods. Typing is static.
An inherited class is in a subtyping relationship with its ancestor class.
Java does not have parameterized classes. One gets two types of
polymorphism: ad hoc by overloading, and of inclusion by
redefinition.
It is multi-threading and supports the development of distributed
application whether using sockets or by invoking methods of remote objects
(Remote Method Invocation).
The principles of its implementation are close to those of Objective CAML. A
Java program is compiled to a virtual machine (JVM). The loading of code
is dynamic. The code produced is independent of machine architectures,
being interpreted by a virtual machine. The basic datatypes are specified
in such a way as to guarantee the same representation on all architectures.
The runtime is equipped with a GC.
Java has important class libraries (around 600 with the JDK,
which are supplemented by many independent developments).
The main libraries concern graphical interfaces and I/O operations
integrating communication between machines.
Differences with Objective CAML
The main differences between Java and Objective CAML come from their type
system, from redefinition and from overloading of methods.
Redefinition of an inherited method must use parameters of exactly the same
type. Method overloading supports switching the method to use according to
the types of the method call parameters. In the following example class
B inherits from class A. Class B
redefines the first version of the to_string method,
but overloads the second
version. Moreover the eq method is overloaded since the type of the
parameter (here B) is not equal to the type of the parameter of the
inherited method (here A). In the end class B has two
eq methods and two to_string methods.
class A {
boolean eq (A o) { return true;}
String to_string (int n ) { }
}
class B extends A {
boolean eq (B o) { return true;}
String to_string (int n ) { }
String to_string (float x, float y)
}
Although binding is late, overload resolution, that is determination of
the type of the method to use, is carried out on compilation.
The second important difference derives from the possibility of casting the
type of an object, as would be done in C. In the following example, two
objects a and b are defined, of class A and B
respectively. Then three variables c, d and e are
declared while imposing a type constraint on the affected values.
{
A a = new A ();
B b = new B ();
A c = (A) b;
B d = (B) c;
B e = (B) a;
}
Since the type of b is a subtype of the type of a, the cast from
b to c is accepted. In this case the type constraint may be
omitted. On the other hand the two following constraints require a
dynamic type test to be carried out to guarantee that the values in c
and in a do in fact correspond to objects of class B. In this
program this is true for c, but false for a. So this last
case raises an exception. While this is useful, in particular for
graphical interfaces, these type constraints can lead to exceptions being
raised during exception due to erroneous use of types. In this Java is
a language typed partly statically and partly dynamically. Moreover the
absence of parameterized classes quite often obliges one to use this feature
to write generic classes.