Classes versus prototypes

\nop{ An object is an entity that comes into existence during an actual computation. } Object creation may be static, in which case all objects are created at the beginning of a computation, or dynamic. Dynamic object creation allows objects to come into existence at the moment that they are needed. The three languages mentioned, Smalltalk, C++ and Eiffel, all support dynamic object creation.

Types

\oopindex{types} An object is an instance of a class. A class acts as a template for creating objects. In a strictly typed language, where strictly typed means that each expression in the language may be assigned a type, the type of an object is determined by the class of which it is an instance. Dynamically, an object may be regarded, using the characterization given in the annotated reference manual for C++, as a region of storage, {\it the meaning of which is determined by the type of the expression used to access it}. See  [ES90]. Static typing allows to resolve the well-typedness of a program at compile-time and enables to deal in an efficient way with method calls, provided that these are not overridden in an inheritance hierarchy. Smalltalk is an untyped language, that enforces no type checking. However, Smalltalk may be regarded as a dynamically typed language, since each computational entity created during the execution of a program is an object in the sense of being an instance of a class. Each object carries its own type information, telling to which class it belongs. When executing a method in response to a message, the object searches its method table, which is shared with the other instances of its class, for the appropriate procedure. When a method is not defined in the object's own method table, the method tables of the classes from which the object inherits are searched. The language C++, in contrast, is statically and strictly typed, although it allows for exceptions to the type scheme. Calling a method, which is called a member function in C++, amounts to calling an ordinary function since the existence of that function may be assessed at compile-time. However, for a function declared virtual, which allows such a function to be overridden by inheriting classes, the appropriate binding cannot be resolved statically but must be computed at run-time.

Classes and instances

\oopindex{class} \oopindex{instance} Classes are templates for creating objects as instances of a class. Being an instance of a class, an object embodies the functionality of that class as well as the functionality inherited from the classes of which the object's class is a subclass. In other words, in a class-based system, we have two relations that determine the behavior of an object, the instance relation, denoting that an object is an instance of a class, and the subclass relation, indicating that a class is a subclass of a class. We may capture these relations pictorially by the arrows \begin{center} .so rel \end{center} which must be read, respectively as, class C is a subclass of (the parent) class P, and object O is an instance of class C. \nop{ As an example, the picture below represents the case that we have an object i that is an instance of a class Integer, which is a subclass of the class Sortable. \begin{center} .so sort \end{center} } As an example, imagine the case that we have an object i that is an instance of a class Integer, which is a subclass of the class Sortable. Using inheritance allows to create an abstract superclass, such as the class Sortable, that contains the common properties of a number of subordinate classes. An example of such a property is the existence of the relation less-than by which instances of (subclasses of) Sortable may be compared and which can be used to define a generic sorting algorithm. As another subclass of Sortable, think of a class String that supports a lexicographical ordering among strings. \oopindex{object creation} Having classes as a means to create objects, it is rather natural to introduce a mechanism that allows all instances of a certain class to share class-wide resources. Smalltalk, for example, allows to declare so-called class variables and class methods that are, in opposition to the common instance variables and methods, shared by all objects of that class. Class-variables are in other words a kind of global variable, with access restricted to the instances of the class. \oopindex{class methods} Class-methods are procedures. These procedures are not allowed to access the instance variables defined for that class since these are private to each instance. Calling a class method is possible without creating an instance of the class. Class-methods are often used to create and initialize instances of a class. \oopindex{members} In C++, variable or function members may be declared static. Static members are shared by all instances of a class, similar to class variables and class methods in Smalltalk. Like class methods, static member functions are not allowed to access ordinary member variables.

Prototypes

\oopindex{prototypes} The disadvantage of making a distinction between the functionality of classes (supporting class variables and class methods) and objects (that are instances of classes, supporting instance variables and ordinary methods), is that programmers are faced with the complexity of making a design choice with respect to where functionality must be put. The choice between class methods or (object) methods will not always be evident. An alternative approach to creating objects is sketched in  [US87], where prototypes are introduced as a unifying concept combining the functionality of classes and objects. Prototypes may be used as templates for creating objects, by cloning, and as computational entities that execute a method in response to a message. Cloning an object amounts to making a copy of an object, including its state at the moment the copy is made. \oopindex{object copying} An interesting variant of cloning is to allow for differential copying, in which the differences with respect to certain attributes of the cloned object can be stated when creating the copy. In effect, the newly created object then inherits the functionality of the object from which it is created, possibly overriding or adding behavior by its differential specification. See also  [RC91]. \oopindex{delegation} As an alternative way to share behavior between objects, inheritance may be implemented as delegation to a designated parent object. Using delegation instead of subclassing or differential cloning to effect inheritance allows to build inheritance structures dynamically, during the computation. The advantage of using prototypes instead of classes to organize the conceptual structure of a program lies first of all in the simplicity that arises from the absence of classes. The primary relation supported by such an approach is the inherits relation, for which we have the choice to allow static inheritance by means of differential specifications or dynamic inheritance by making use of delegation. An additional advantage of discarding classes is that one-of-a-kind objects are naturally supported, since no extra class for such an object needs to be introduced. Another advantage, mentioned in  [US87] is that the problem of whether to support metaclasses, and to what extent, does not occur.