www.marco cantu.com
|
|
Comparing OOP Languages
Java, C++, Object Pascal
This text is a work in progress: suggestions and corrections are welcome. This paper is copyright Marco Cantù 1997 and cannot be distributed without permission. Version 1.3, last updated on November 15th 1997.
Java is a popular Internet language, C++ used to
be the most common OOP language, and Object Pascal is the language
Borland uses inside Delphi. Although this is not immediately evident,
these three languages have many things in common. The aim of this
presentation is to delve into technical aspects of the three languages,
comparing them. I'm not trying to assess which is the best language,
because this largely depends on what you want to use it for.
This presentation requires a minimum knowledge of
one of the OOP languages discussed, or at least a basic knowledge
of OOP concepts in general. I'll just describe why a certain language
feature is important, then I'll do on comparing it in the three
languages. I won't show you how to use these language features
in actual examples. I don't want to teach you OOP, only to compare
these languages.
Key OOP Features
Object-Oriented Programming (OOP) is not a new programming
technique. Its roots date back to Simula-67, although its first
complete implementation relates to Smalltalk-80. OOP became popular
in the second part of the of the 80ies, with so diverse languages
as C++, Objective-C (another extension of C), Object and Turbo
Pascal, CLOS (an OOP extension of Lisp), Eiffel, Ada (in its last
incarnations), and more recently Java. In this presentation I'll
focus only on C++, Object Pascal and Java, with limited references
to other OOP languages.
The key OOP features are well know, and I'm covering
them only to be able to use a common terminology with you, before
we proceed.
- The first key feature is the definition of classes,
abstract data types which encapsulate their representation, and
make available some operations, or methods. Classes are usually
the basis of modularity, encapsulation, and data abstraction in
OOP languages.
- The second key feature is inheritance, a way
to define a new type inheriting the elements (representation and
methods) of an existing one and modifying or extending it. This
favors the expression of specialization and generalization.
- The third feature is known as polymorphism, and
allows you to refer to objects of different classes (usually within
a sub-hierarchy) in a homogeneous way. This makes the classes
even more reusable, the programs more easy to extend and maintain.
Classes, inheritance, and polymorphism are fundamental
features required by a languages to be described as an OOP language.
(Languages not having inheritance and polymorphism, but only classes,
are generally indicates as class-based). Having said this,
different OOP languages follow completely different approaches.
We can discriminate among different OOP languages comparing type
checking mechanisms, the ability to support different programming
models, and the object model they support. Then I'll move to specific
language features.
Compile-Time vs. Runtime Type Checking
Programming languages can be evaluated rating how
much "strongly-typed" they are. The checks on the type
relate to the existence of the methods being called, the types
of their parameters, the array range checks, and so on.
C++, Java, and Object Pascal all favor compile-time
type-checking, more or less extensively. Of the three C++ is probably
the less precise, and Java the one enforcing type checking at
the highest extent. The reason is that C++ maintains compatibility
with the C languages, which supports compile-time type-checks,
but in a very light way. For example C and C++ consider the arithmetic
type as being all compatible (although when assigning a float
to an int the compiler issues a warning). In Object Pascal
and Java a Boolean value is not an integer, and a characters is
another different and incompatible type.
The fact that the Java virtual machine "interprets"
the byte-code at runtime, doesn't mean that the language gives
up the compile-time type-checking. On the contrary, in this language
the checking is more thorough. Other OOP languages as Smalltalk
and CLOS, instead, tend to do most if not all of the type checking
at runtime.
Hybrid vs. Pure OOP Languages
Another differences in among pure and hybrid OOP
languages. Pure OOP languages are those allowing only one programming
model, OOP. You can declare classes and methods, but you cannot
have plain old functions and procedures, and global data.
Among our three languages, only Java is a pure OOP
language (as Eiffel and Smalltalk are), which at first seems a
very positive idea. However, you end up using a lot of static
methods and static data, which is not that different from using
global functions or data, beside the more complex syntax. In my
opinion pure OOP languages offer an advantage for OOP newcomers,
because programmers are forced into using (and learning) the object
oriented programming model. C++ and Object Pascal, instead, are
two typical example of hybrid languages, which allow programmers
to use traditional C and Pascal programming approaches.
Notice that Smalltalk extended this concept of having
only objects up to the level of defining as objects also the predefined
data types, as integers and characters, and the language constructs
(as the looping instructions). This is theoretically interesting,
but reduces the efficiency quite a lot. Java stops much earlier,
allowing the presence of native, non OOP, data types (although
there are wrapper classes for the native types).
Plain Object Model vs. Object Reference Model
A third element discriminating OOP languages is their
object model. Some traditional OOP languages allow programmers
to create objects on the stack, the heap and the static storage.
In these languages a variable of a class data type corresponds
to an object in memory. This is how C++ works.
Lately, there seems to be a trend to use a different
model , called object reference model. In this model every object
is allocated dynamically on the heap, and a variable of a class
type is actually a reference or a handle to the object in memory
(technically something similar to a pointer). Java and Object
Pascal both adopt this reference model. As we'll see in a while
this means that you should remember to allocate memory for the
object.
Classes, Objects, and References
- Feature: Since we are discussing OOP languages, after this
introduction, the starting point is to discuss classes and objects.
I hope everyone clearly understands the difference between these two
terms: in short, a class is a data type, an object is an instance of
a class type. Now how to we use objects in languages using different
object models?
- C++: In C++, if we have a class MyClass with the method
MyMethod, we can write
MyClass Obj;
Obj.MyMethod();
and get an object of the MyClass class named
Obj. The memory for this object is typically allocated
on the stack, and you can start using the object right away, as
in the second line above.
- Java: In Java a similar
instruction allocates only the memory space for the handle to
the object, not for the object itself:
MyClass Obj;
Obj = new MyClass();
Obj.MyMethod();
Before you use the object, you have to call new to
allocate the memory for the object. Of course, you should declare
and initialize the object with a single statement whenever possible,
to avoid using un-initialized objects handles:
MyClass Obj = new MyClass();
Obj.MyMethod();
- OP: Object Pascal has
a very similar approach, but requires different statements for
the declaration and the initialization:
var
Obj: MyClass;
begin
Obj := MyClass.Create;
Obj.MyMethod;
- Note: If the object reference
model seems to require more work for the programmer, keep in mind
that in C++ you often have to use pointers to objects and references
to objects. Only using pointers and reference for example, you
can get polymorphism. The object reference model, instead, makes
the pointers the defaults, but does a good job hiding them. In
Java, in particular, there are officially no pointers, but pointers
are everywhere. Only programmers have no direct control over them,
so that they cannot access random memory locations, for security
reasons.
The Recycle Bin
- Feature: Once you have
created and used an object you need to destroy it, to avoid using
unnecessary memory.
- C++: In C++ destroying
objects allocated on the stack is fairly simple. Handling the
destruction of object allocated dynamically, on the other hand,
is often a complex issue. There are many solutions including reference
counting and smart pointers, but this is far from a simple issue.
The first impression for C++ programmers is that using a reference
object model makes the situation even worse.
- Java: This is certainly
not the case with Java, since the virtual machine runs a garbage
collection algorithm in the background. This is something
programmers get for free, but something that might adversely affect
the performance of applications. Not having to write destructors
may lead to logical errors in the cleanup code.
- OP: Object Pascal, instead,
has no garbage collection mechanism. However Delphi components
support the idea of an owner object: the owner becomes responsible
for destroying all the object is owns. This makes handling the
object destruction very simple and straightforward.
Defining New Classes
- Feature: Now that we've
seen how to create objects of the existing classes, we can focus
on the definition of new classes. A class is simply a collection
of methods, operating on some local data.
- C++: This is the C++ syntax of a simple class definition:
class Date {
private:
int dd;
int mm;
int yy;
public:
void Init (int d, int m, int y);
int Day ();
int Month ();
int Year ();
};
And here is the definition of one of the methods:
void Date::Init (int d, int m, int y)
{
dd = d;
mm = m;
yy = y;
}
- Java: Java syntax is very
similar to C++ syntax:
class Date {
int dd = 1;
int mm = 1;
int yy = 1;
public void Init (int d, int m, int y) {
dd = d; mm = m; yy = y; }
public int Day () { return dd; }
public int Month () { return mm; }
public int Year () { return yy; }
}
The biggest difference is that the code of each method
is written directly when it is declared (without making the function
an inline function, as happens in C++), and that you can initialize
the data members of the class. Actually if you fail do to so Java
initializes all the data members for you, using a default value.
- OP: In Object Pascal the
syntax of the class declaration is different, and more similar
to C++ than to Java:
type
Date = class
private
dd, mm, yy: Integer;
public
procedure Init (d, m, y: Integer);
function Month: Integer;
function Day: Integer;
function Year: Integer;
end;
procedure Date.Init (d, m, y: Integer);
begin
dd := d;
mm := m;
yy := y;
end;
function Date.Day: Integer;
begin
Result := dd;
end;
As you can see there are syntactical differences:
methods are defined with function and procedure keywords, the
methods without parameters have no parenthesis, methods are simply
declared inside the class definition, then defined later on, as
usually happens in C++. However, Pascal uses the dot notation,
while C++ relies on the scope operator (an operator not available
in Object Pascal and Java).
- Note: Accessing to
the current object. In OOP languages method are different
from global functions because they have an hidden parameter, a
reference or pointer to the object we are operating on. This reference
to the current object simply takes a different name. It is this
in C++ and Java, self in Object Pascal.
Constructors
- Feature: The above class
is terribly simple. The first thing we can add to it is a constructor,
which is a good technique for solving the problem of objects initialization.
- C++: In C++, as in Java,
constructors have the same name of the class. If you don't define
any constructor the compiler synthesizes a default constructor,
adding it to the class. In both these languages you can have multiple
constructors thanks to methods overloading.
- Java: Everything works
as in C++, although constructors are also called initializers.
This highlights the fact that is the Java virtual machine to create
the objects, while the code you write in a constructor simply
initializes the newly created object. (The same actually happens
also in Object Pascal.)
- OP: In Object Pascal you
use a specific keyword, constructor. In this language there
is no method overloading, but since constructors have custom names
name, you can provide several constructors with different names.
In this language each class has the default Create constructor,
unless you override it with a constructor having the same name
and eventually different parameters. This constructor is simply
inherited by a common base class, as we'll see later on.
Destructors and finalize()
- Feature: A destructor
has the opposite role of a constructor, and is generally called
when an object is destroyed. If most classes need a constructor,
only few of them need a destructor. A destructor should basically
free resources allocated by the constructor (or by other methods
during the life of the objects). These resources include memory,
files, database tables, Windows handles, and so on.
- C++: C++ destructors are
automatically called when an objects goes out of scope, or when
you delete a dynamically allocated object. Every class can have
only one destructor.
- OP: Object Pascal destructors
are similar to C++ destructors. Object Pascal uses a standard
virtual destructor, called Destroy. This destructor is
called by the standard Free method. All objects are dynamic,
so you are supposed to call Free for each object you create, unless
it has an owner responsible for its destruction. In theory you
can declare multiple destructors, which makes sense because you
call destructors in your code (there is nothing automatic).
- Java: Java has no destructors.
Objects without references are destroyed by the garbage collection
algorithm, which runs as a background task. Prior to destroying
an object the garbage collector calls the finalize() method.
However there is no guarantee that this method is actually called
(at least in Java 1.0). For this reason if you need to free resource
you should add a custom method, and ensure it is called.
Class Encapsulation (Private and Public)
- Feature: A common element
of the three language is the presence of three access specifiers
indicating different levels of class encapsulation, public, protected,
and private. Public means visible by every other class, protected
means visible by derived classes, private means no external visibility.
The details, however, are different.
- C++: In C++ you can use
the friend keyword to by pass encapsulation. The default
visibility for a class is private, for a struct is public.
- OP: In Object Pascal,
private and protected have effect only for classes in different
units. A class is friend of every other class declared in the
same unit (or source code file). Delphi has two more access specifiers,
published and automated. Published generates RTTI information
for the element, automated an OLE Automation interface.
- Java: In Java, a syntactical
difference is that access specifiers are repeated for every class
member. A more concrete difference is the default in Java is friendly,
which means the element is visible also by other classes of the
same package (or source code file, similarly to what happens in
OP). Similarly, the protected keyword indicates the visibility to subclasses, but also to other classes of the same package, while the private protected combinations corresponds to C++ protected.
Files, Units, and Packages
- Feature: An important
difference between the three languages is the organization of
the source code in files. All three languages use files as standard
mechanism for storing the source code (differently from other
OOP languages, as Smalltalk), but while the C++ compiler doesn't
understand files, the OP and Java compilers do. Both languages
work with the idea of module, although the concept assumes a different
name.
- C++: In C++, programmers
tend to place class definitions in header files, and method definitions
in separate code files. Usually the two files have the same name
and a different extension. A compilation unit generally refers
(includes) its own declaration file plus the declaration files
for the classes (or functions) the code refers to. These are all
conventions the compiler doesn't enforce. This means that the
linker has a lot of work to do, because the compiler cannot anticipate
in which other module a method will be defined.
- OP: In Object Pascal,
each source code file is called unit, and is divided in
two parts, the interface and the implementation,
marked by these two keywords. The interface section includes the definition of the class or classes (with the declaration of the methods), and the implementation section must include the definition of the methods declared in the interface.
It is illegal to write actual code in the interface section.
You can refer to the declaration in another file with a uses statement.
This includes the interface of that file in the compilation:
uses
Windows, Form, MyFile;
- Java: In Java, each source
code file, or compilation unit, is compiled separately. You can
then mark a group of compilation units as being part of a single
package. Differently than the other two languages, you write all
of the code of the methods as you declare the class. When a file
is included, with an import statement the compiler reads
only its public declarations, not all of its code:
import where.myclass;
import where.* // all the classes
- Note: Modules as name
spaces. Another important difference is that Java and OP compilers
can read a compiled file and extract its definition, as it you
were extracting the header file from the compiled code. As an
aside, the C++ language introduced namespaces to overcome
the absence of a module structure. In Java and OP, in fact, when
two names clash, you can generally prefix the name with the module
name. This doesn't require the extra work of set up namespaces,
but it's built in the languages.
Class/Static Method and Data
- Feature: OOP languages
generally allow to have some methods and data which relates to
the class as a whole, not to specific objects. Class method generally
can be called both for an object of the class or applied to the
class type as a whole. Class data is data not replicated for each
object, but shared among them.
- C++: In C++ class method
and data are indicated by the static keyword. Class data
must be initialized with a specific declaration: this is one of
the drawbacks of the absence of modules.
- OP: OP has only class
method, which are indicated by the class keyword. Class
data can be replaced by adding a private global variables to the
unit which defines the class.
- Java: Java uses the same
keyword of C++, static. Static methods are used very often
(and even overused) because of the absence of global functions.
Static data can be directly initialized in the class declaration
Classes and Inheritance
- Feature: Inheritance among
classes is one of the foundations of OOP. It can be used to express
generalization or specialization. The basic idea is that you define
a new type extending or modifying an existing type, in other words
a derived class has all of the data and methods of the base class,
plus new data and method, and eventually modifies some of the
existing methods. Different OOP languages have a different jargon
for the mechanism (derivation, inheritance, subclassing), the
class you inherit from (base class, parent class, super class),
and the new inherited class (derived class, child class, subclass).
- C++: C++ uses the keywords
public, protected, and private to define
the flavor of inheritance, and hide the inherited methods or data,
turning them to private or protected. Although the public
inheritance is the most used version, the default is private
inheritance. C++ is the only of these three languages with multiple
inheritance, as we'll see later on. Here is an example of the
syntax:
class Dog: public Animal {
...
};
- OP: Object Pascal uses
no keyword to express inheritance, but a special syntax, adding
the base class name within parenthesis. The language supports
only what C++ calls public inheritance. OP classes have a common
base class, as we'll see later on.
type
Dog = class (Animal)
...
end;
- Java: Java uses the extends
keyword to express the only kind of inheritance, which corresponds
to public inheritance in C++. Java has no support for multiple
inheritance. Java classes have a common base class, as we'll see
later on.
class Dog extends Animal {
...
}
- Note: Base class constructors
and initialization. Constructors of inherited classes have
a complex structure both in C++ and Java. In Object Pascal this
it is the programmers responsibility to initialize the base class.
This topic is quite complex, so I've skipped it in this presentation.
Instead I'll focus on the common base class, access to the base
class, multiple inheritance, interfaces, late binding, and other
related topics.
The Mother of All Classes
- Feature: In some OOP languages
every class has at least a default base class. This class, often
called Object or something similar, has some basic capabilities
shared by all classes. This base class, in fact, is the class
from which all the other classes ultimately inherit. This is a
common approach because it's what Smalltalk originally did.
- C++: Although the C++
language doesn't have these feature, many application frameworks
based on it introduce the idea of a common base class. MFC is
a notable example, with its CObject class. Actually this
made more sense at the beginning, when the language lacked features
as templates (and even more when it lacked multiple inheritance.
- OP: Every class automatically
inherits from the TObject class. Since the language lacks
multiple inheritance all the classes form a huge hierarchical
tree. The TObject class can handle RTTI and has few other capabilities.
- Java: As in OP, all the
classes implicitly inherit from the Object class. Also
in this language the common base class has limited capabilities.
Accessing Methods of the Base Class
- Feature: When you write
a method of a class, or override a method of the base class, you
often need to refer to methods of the base class. If the method
is redefined in the derived class, using its name you'll access
to the new version. OOP languages have some techniques or keyword
to solve this problem.
- C++: In C++ you can use
the scope operator (::) to refer to a specific class. You
can access to the base class, but also to a class higher up in
the hierarchy.
- OP: Object Pascal has
a specific keyword to do this, inherited. after this keyword
you can write the name of the base class method you want to call,
or (in certain circumstances) simply use the keyword to access
to the corresponding base method.
- Java: Java uses the super
keyword to accomplish the same thing. In this language, but also
in OP, there is no way to refer to another ancestor class. This
might seem a limitation at first, but it allows to extend a hierarchy
by adding intermediate classes. At the same time if you don't
need the functionality of a base class you probably should not
inherit from it!
Subtype Compatibility
- Feature: Not all the OOP
languages are strongly types, as I mentioned at the beginning,
but the three we are focusing on all share these feature. This
basically means that objects of different classes are not type-compatible.
There is an exception to this rule: objects of derived classes
are compatible with the type of their base class. (Notice: the
reverse is not true.)
- C++: In C++ the subtype
compatibility rule is valid only for pointers and references,
not for plain objects. In fact, different objects have difference
sizes, so you cannot accommodate them in the same memory location.
- OP: The subtype compatibility
is available for every object, thanks to the object reference
model. Moreover, all the objects are type-compatible with the
TObject type.
- Java: Java shares exactly the same model of Object Pascal.
- Note: Polymorphism.
Subtype compatibility in particularly important to obtain late
binding and polymorphism, as described in the next section.
Late Binding (and Polymorphism)
- Feature: When different
classes of a hierarchy redefine a method of their base class,
it is very powerful to be able to refer to a generic object of
one of these classes (thanks to the subtype compatibility) and
call a method, which results in a call of the method of the proper
class. To accomplish this the compiler should support late binding,
that is it should not generate a specific function call, but wait
until runtime to determine the actual type of the object and the
function to call.
- C++: In C++ late binding
is available only for virtual methods (which become slightly slower
to call). A method defined as virtual in the base class maintains
this feature when it is redefined (but only if the method signature
matches). Plain, non-virtual methods, do not allow late binding,
as in Object Pascal.
- OP: In Object Pascal late
binding is introduced with the virtual or dynamic
keywords (the difference between the two is only an technical
implementation difference). In derived classes redefined methods
should then be marked with the override keyword (this force
a compiler check on the method signature). This is a peculiar
aspect of OP, and the rationale behind it is that this allows
for more changes in the base class.
- Java: In Java all methods
use late binding, unless you explicitly mark them as final.
Final methods cannot be redefined, and are faster to call. Also
in Java writing methods with the proper signature is vital to
obtain polymorphism. The fact that in Java the default is late
binding, while in C++ the default is early binding is a clear
sign of the different approach of the two languages: C++ at times
sacrifices the OOP model to favor efficiency.
- Note: Late binding for constructors and destructors.
Object Pascal, contrary
to the other two languages, allows to define virtual constructors.
Virtual destructors, instead, are supported by all three languages.
Abstract Methods and Classes
- Feature: When building
a complex hierarchy, programmers often need to introduce methods
in higher level classes, to obtain polymorphism, even if the methods
are not jet defined for that specific abstraction. Beside leaving
the method empty, many OOP language implement specific mechanism,
as the definition of abstract methods, that is methods without
an implementation. Classes having at least one of abstract method
are often called abstract classes.
- C++: In C++ abstract methods,
or pure virtual functions, and are obtained appending the so-called
pure specifier (=0) to the method definition. Abstract
classes are simply classes with (or inheriting) one or more abstract
methods. You cannot create an object of an abstract classes.
- OP: Object Pascal uses
the abstract keyword to mark these methods. Again, abstract
classes are classes having or inheriting abstract methods, but
you can create an instance of an abstract class (although the
compiler emits a warning message). This exposes a program to the
risk of calling an abstract method, an event that generates a
runtime error and terminates the program.
- Java: In Java both abstract
methods and abstract classes are marked with the abstract keyword
(actually in Java it is compulsory to define as abstract a class
which has abstract methods--although this seems a little redundant).
Also derived classes which do not redefine all of the abstract
methods must be marked as abstract classes. As in C++, it isn't
possible to create instances of abstract classes.
Multiple Inheritance and Interfaces RTTI Exceptions Handling
- Feature: The basic idea
of exceptions handling is to simplify the error handling code
of a program, providing a standard build in mechanism, with the
goal of making programs more robust. Exceptions handling is a
topic deserving a full presentation, so I'll just sketch some
key elements and differences.
- C++: C++ uses the throw
keyword to generate an exception, the try keyword to mark
a guarded block, and the catch keyword to write the exceptions
handling code. Exceptions are generally object of special classes,
possibly forming a hierarchy in all three languages. C++ performs
stack unwinding, destroying (and calling destructors) for all
of the objects on the stack.
- OP: Object Pascal uses
similar keywords, raise, try, and except,
and has similar capabilities. The only real difference is that
there is no stack unwinding, simply because there are no objects
on the stack. As an alternative you can add a finally keyword,
to indicate code that should always be executed, regardless of
the fact that an exception has been raised or not. In Delphi exception
classes are derived from Exception.
- Java: Uses the C++ keywords,
but has the same behavior of Object Pascal , including the extra
finally keyword. This is common to all the languages with
an object reference model. The presence of a garbage collection
algorithm limits the use of finally to class which allocate
resources other than memory. Java is also more rigorous in pretending
that all the functions that can raise an exception have a proper
exception clause indicating which exceptions the function can
raise. This is checked by the compiler. This is a powerful technique,
and is usually well regarded even if it implies more work for
the programmer. In Java classes of exception objects must inherit
from the Throwable class.
Templates (Generic Programming)
- Feature: Generic programming
is a technique for writing functions and classes leaving some
data types unspecified. The type specification takes place when
the function or class is used in the source code. Everything is
strictly under the supervision of the compiler, and nothing is
left to determine at runtime. The most typical example of template
classes is that of container classes.
- C++: Only C++ (of these
three languages) has generic classes and functions, indicated
by the template keyword. The C++ standard includes a huge
template class library, called STL, which support a peculiar and
powerful programming style.
- OP: Object Pascal has
no template. Container classes are generally built as containers
of objects of the TObject class.
- Java: Has no templates,
as well. You can use containers of Objects, or resort to other
tricks.
Other Specific Features
- Feature: There are other
features I've not covered, because they are not fundamental, and
they are specific of only one language.
- C++: I've already mentioned
multiple inheritance, virtual base classes, and templates. This
are features missing in the other two OOP languages. C++ has also
operator overloading, while method overloading is present also
in Java. C++ allows programmers to overload also global functions.
You can overload also the type cast operators, writing type conversion
methods that might be called behind the scenes. The C++ object
model requires copy constructors and the overloading of assignment
operators, something the other two language don't need, because
they are based on an object reference model.
- Java: Only Java supports
multithreading right into the language. Objects and methods support
synchronization mechanisms (with the synchonized keyword):
two synchronized methods of the same class cannot be executed
at the same time. To create a new thread you can simply derive
from the Thread class, overriding the run() method.
As an alternative you can implement the Runnable interface
(this is what you typically do in an applet which supports multithreading).
We've already discussed the garbage collector. Another key feature
of Java, of course, it the idea of portable byte-code, but this
is something that doesn't strictly relate to the language.
- OP: Some special features
of Object Pascal are class references, easy to use method pointers
(which are the basic of the event model), and in particular properties.
A property is just a name hiding the way you access the data of
a method. A property can map to a direct read or write of data,
or can refer to access methods. Even if you change the way the
data is accessed, you don't need to change the calling code (although
you have to recompile it): this makes property a very powerful
encapsulation feature. Java is supposed to add this feature to
the language in version 1.1, to support Java Beans.
Standards
- Feature: Every language
requires someone setting a standard, and checking that all the
implementations conform to it.
- C++: The ANSI/ISO C++
standard committee has almost finished a time-consuming standardization
effort. Most of the compiler writers seems to try to comply with
the standard, although there are still many peculiarities. In
theory the development od the language has come to a stop. In
practice, initiatives as the new Borland C++ Builder certainly
make no good to the situation, but many feel that C++ badly needs
visual programming environments. At the same time the popular
Visual C++ stretches C++ in other directions, for example with
a clear abuse of macro statements. My opinion is that each language
has its own development model, and it makes little sense to try
using a language for something it was not planned for.
- OP: Object Pascal is a
proprietary language, so it has no standard. Borland has licensed
the language to a couple of small OS/2 compiler vendors, but this
has had little impact. Borland is extending the language at each
release of Delphi.
- Java: Java is a proprietary
language, too, and has even a trademark on the name. However Sun
seems to be more than willing to license it to other compiler
vendors. Sun is keeping control of the language and seems to be
unwilling to have an official standardization body take care for
it, at least for the moment. Sun is also trying to avoid the development
of virtual machines which do not conform to the standard.
Conclusion: Languages and Programming Environments
As I mentioned above, although I've tried to examine
these language only comparing syntactical and semantic features,
it is important to consider them in the proper context. These
languages target different needs, are meant to solve different
problems in different ways, and are used within highly different
programming environments. Although both the languages and their
environment are copying each other features, the were build with
different needs in mind, and this is something you can see when
comparing their features. C++ goal is power and control, at the
expense of complexity; Delphi goal is easy, visual programming,
without giving up to mush power, and strong connection with Windows;
Java aim is portability, even giving up some of the speed, and
distributed applications (or executable Web content).
What can determine the success of these three languages
are not their language features I have covered in this presentation.
The financial status of Borland, the operating system control
of Microsoft, the popularity of Sun in the Internet world (and
the fact it is seen as the anti-Microsoft by some), the future
of Web browsers and of the Win32 API, the role of ActiveX (and
Delphi ActiveForms), are all factors which might affect your choices
more than technical elements. For example a very nice language
as Eiffel, from which both Object Pascal and Java have taken more
than some inspiration, never got any real market share, although
it has been popular in universities around the globe.
Just keep in mind that "trendy"
is becoming a common word in the computer world as never before.
As users like to have this year model of toolbar (this is probably
the reason OSes are named after the year the are released), programmers
love working with the last programming language, and be the first
to master it. We can say that "Java is not the last
of the OOP languages", someone in the next few years will
come up with a new trendy language, everyone will jump onto that
bandwagon, thinking he cannot remain behind, and forgetting that
most of the programmers in the world still type on their keyboard
nice Cobol statement!
Author
Marco Cantù is author of books on two of
the three languages discussed here, Object Pascal and C++, published
in the US and many other countries. He writes (more or less regularly)
for several magazines, and does training courses on OOP languages
and on Windows programming with his company, WinTech Italia. He
enjoys speaking at many conferences, worldwide. You can reach him on www.marcocantu.com.
|