|
The Darwin Project |
|
|
[Darwin] [Lava: Delegation Consultation Multiplicity] [Benefits] [Implementation] |
|
|
Aims |
The Darwin project aims to improve the foundation of object-oriented systems by bridging the gap between the two families of object-oriented languages known today: class-based and prototype-based ones. We want to step beyond the pro and contra discussion of classes versus prototypes, inheritance versus delegation, and safety versus flexibility by investigating
|
|
Results |
The current results of the project are:
|
The Darwin Model
|
|
|
Classes, |
The Darwin model describes typed, class-based object-oriented languages extended by static and dynamic object-based inheritance (also known as delegation). Please make sure you understand what is delegation, before reading further. From a programmer´s point of view Darwin is interesting because it eases their work and promotes unanticpated reuse. From a theoretical point of view its main achievment is the safe integration of static and dynamic delegation with static typing and subtyping. The Darwin model is best illustrated by the design of the Lava language. [A better tutorial than the following description is certainly overdue.]
|
The Lava Language
|
|
|
Java
plus |
Lava is an extension of Java by static and dynamic delegation and consultation. An overview of its specific syntax and semantics is given in the following, using the example from the annotated strategy pattern description. The class Formatting corresponds to the class Compositor from the original example scenario and the class LineBreaking corresponds to the class Compositor. |
Delegation
|
|
|
Syntax
|
In Lava definition of objects that delegate part of their behaviour and state to other objects just requires adding the keyword delegatee to an instance variable definition. |
|
Dynamic |
For instance, a class of text formatting objects (Compositor) that uses different line breaking strategies (encapsulated in class LineBreaking and its subclasses) can be written as simple as
The Formatting class may use all methods of the LineBreaking type as if they where locally defined or inherited from a superclass - with the essential difference that it may dynamically switch to a different set of method implementations simply by assigning an object of a different LineBreaking subtype to the lineBreak variable! The use of the @-prefix to LineBreaking in the declaration "delegatee @LineBreaking lb;" says that all subtypes of LineBreaking that do not delegate to LineBreaking are legal values of lb. This restriction is required to ensure type-safety of dynamic delegation (see Darwin thesis). Read @ as a mnemonic for "atomic": in Darwin, objects that implement a type themselves - without delegating part of the implementation - are said to be "atomic intstances" of that type. Note that in the current implementation of Lava atomic types are not indicated by prepending @. Instead, the keyword atomic can be added to the corresponding declaration. The line
is written as
|
|
Overriding |
Like in the case of class-based inheritance, the Formatting class can fine tune the "inherited" behaviour via overriding. For instance, assume that the line breaking algorithm calls the method getStretchability() to determine by how many pixels individual text components can be stretched. Then providing a specialized version of this method might be all that is needed to adapt the inherited behaviour to the current delegator´s needs.
|
|
Static |
Static delegation, that is delegation to one fixed parent object, is always safe, even if the values of the delegation field are unrestricted. For instance, one can use the following Lava idiom to implement an overriding decorator (i.e. one that adds own methods and overrides methods of the decorated type):
Note that static object-based inheritance still is more dynamic than class-based inheritance. The exact behaviour of an instance of OverridingDecorator can be determined at run-time, by passing subtypes of Decorated as constructor parameters: OverridingDecorator od; ... od = new SubtypeOfDecorator(new SubtypeOfDecorated()); |
|
Power ... |
Note that
achieving the effect of dynamic behavior change (strategy pattern) plus
fine-tuning of inherited behaviour by overriding could be awkward or even
impossible without delegation. |
|
... without pain |
In particular, delegation-based implementations
|
Consultation
|
|
|
No |
In certain application scenarios overriding of parent methods might not be needed or even undesirable. In such cases one can use consultation instead of delegation. For instance, the decorator pattern can be implemented in Lava as
|
|
Automatic |
Like in the case of delegation there is no need to write any "forwarding methods" and keep them consistent when the parent interface (e.g. Decorated) changes. The programmer can concentrate on the essence of his work (i.e. implementation of the additional behaviour that motivated the use of the decorator pattern). |
MultiplicityLava has
seen versions with and without multiple delegation. |
|
|
Renaming
|
In the initial design and implementation (see Lava 0.5) an object could have multiple delegatees or consultants. Delegation and consultation could even be used jointly by the same object. Ambiguities had to be resolved by Eiffel-like renaming. However, renaming is no general solution to name clashes. Additional, intricate problems arise in the case of "diamond delegation" (Eiffel users would say "repeated delegation"). They require complex run-time bookkeeping that complicate the semantics and implementation. |
|
No |
Therefore, the new design of Lava eliminated multiple delegation and consultation in favour of simple and consistent semantics. We still consider multiple delegation to be useful in many situations but prefer to wait until we have a better general solution for resolving conflicts among semantically incompatible methods. This is a topic of onging and future work.
|
Benefits
|
|
|
Flexibility
|
The integration of delegation into mainstream object-oriented languages offers an easy way
|
|
Ease
of
|
Compared to design patterns based only on inheritance and aggregation delegation is easy and results in more reusable designs because
|
Implementation
|
|
|
The basic concepts and the implementation scheme for C++, described in Günter's first technical report, were adapted to Java and extended in several ways by Pascal Costanza and Matthias Schickel. In their diploma theses they developed the first proof of concept implementation of Lava as an extension of the Java bytecode compiler and interpreter of the JDK 1.0.2. for Solaris and Windows 32. This implementation was not portable (Lava programs could be executed only on our modified JVM) and its performance was JDK-1.0.2-like ;) Therefore a translation scheme of to standard Java bytecode was developed, which ensures that Lava programs run on any correct JVM implementation and can take advantage of the sophisticated optimizations performed by current HotSpot JVMs. Thanks to the contribution of Uwe Bardey, Tobias Windeln, and Jörg Gonska, its implementation, the lavac compiler, is available for download and is still progressing further. If you are interested in details of any of the different implementation schemes, you can find the documents mentioned above on our papers page. |
|
| © 1997-2002 Günter Kniesel |
|