4
Microprocessing and Microprogramming 34 (1992) 15-18 15 North*Holland A UNIFYING APPROACH TO CLIENTS~IP, DHLEGATION ~{D INHERIT~NCE IN OBJECT O~ENTED LANGUAGES Paola Nieddu Dipartimento di Matematica dell'Universita' di Genova Via L.B. Alberti 4 16132 Genova Itali~ EM: aneona@~etgen.ge.cnr, it Abstract. Clientship, delegation arid inheritance are three mechanisms for sharing kn~ledge among related objects in object oriented languages. This paper reports on a model where the possibility of umifying them into a single construct is explored. The aim is chiefly a theoretical one, to gain a deeper insight into their resemblances and differences. Among inheritance based languages, stronol? typed ones receive a special attention, with the purpose of making th~ &~mparison of the three mechanisms in a strongly typed enviro~ent. At this stage Gf the work, no characteristic of the three i~echanisms is discnrged, in order to point out all the problems. A Modula-2-1~ke syntax of this construct is shown, its semantics is proposed and the mLst chall~ngxng implementative problems are discussed. i. CLIENTSHIP, DELEGATION AND iNHERITANCE Clientship, delegation and inheritance are three mechanisms for sharing knowledge amorg related objects in object oriented languages. Inheritance implements the set-theoretic approach. It is based on the concepts of class and instance. A class collects objects according to their "type", encoding their common behavior and declaring a set of variables that each of its instances must have but with individual values. Instances can share ~thods but not values. Inheritance allows incremental definition o~ classes but not of instances, since they cannot be defined directly in terms one of another. Delegation implements the concrete approach. It removes the notion of "type" ~bjez~ and introduces that of prototype. ~very object can serve as a prototype, and thus it describes the default behavior for a concept. New objects can share part of the knowledge stored in the prototype by saying how they differ from it. Objects can share both methods and variables. Delegation allows incremental definition of all objects, They can be directly defined in terms one of another. The two mechanisms differ not only in how they structure objects bu~ also in the way they i~plement the method lookup. In delegation it is accomplished through message-passlng. If an object has no local method for replying to a message, it forwards the message to its prototypes. In inheritance the method lookup is performed by a primLtive, unchangeable routine. It is easy to see that delegation can implement the functionality of inheritance, but there is not agreement that the opposite is true. The special variable s~If represents a reference to the object that "orlqinaliJ' received the message [2]. With inherlt,;~:E, every time a message is forwarded the self variable is re-bound, so that it is impossible for an object to reply in place of the object which originally received the message. It is not so in delegation, where forwarding a message does not cause the re-bounding of the self variable. Lieberman [2] uses this argument in order to prove that inheritance cannot capture the behavior of delegation so that he argues that delegation is more powerful than inheritance. Stein [3) asserts that the two mechanisms are substantially equivalent. Looking at models like that of Smalltalk [where classes are objects too, because they can have attributes of their own), Stein [3] observes that class inheritance {"is-a" relationship) cannot be interpreted other than delegation of class attributes and shows a formal model where prototypes are mapped into classes. However, in languages where classes are pure types, the approach of Stein [3] is not applicable. A more recent study [4] concludes that inheritance and delegation (sh~ring protocols) are orthogonal with the concepts of class and prototype (organization protocol) and demonstrates that inheritance "has a fundamental speed advantage over delegation in most situations, and that the speed and space optimizations possible for class-based systems usually outweigh the need fo~ the sharing

A unifying approach to clientship, delegation and inheritance in object oriented languages

Embed Size (px)

Citation preview

Microprocessing and Microprogramming 34 (1992) 15-18 15 North*Holland

A UNIFYING APPROACH TO CLIENTS~IP, DHLEGATION ~{D INHERIT~NCE IN OBJECT O~ENTED LANGUAGES

Paola Nieddu

Dipartimento di Matematica dell'Universita' di Genova Via L.B. Alberti 4

16132 Genova Itali~

EM: aneona@~etgen.ge.cnr, it

Abstract. Clientship, delegation arid inheritance are three mechanisms for sharing kn~ledge among related objects in object oriented languages. This paper reports on a model where the possibility of umifying them into a single construct is explored. The aim is chiefly a theoretical one, to gain a deeper insight into their resemblances and differences. Among inheritance based languages, stronol? typed ones receive a special attention, with the purpose of making th~ &~mparison of the three mechanisms in a strongly typed enviro~ent. At this stage Gf the work, no characteristic of the three i~echanisms is discnrged, in order to point out all the problems. A Modula-2-1~ke syntax of this construct is shown, its semantics is proposed and the mLst chall~ngxng implementative problems are discussed.

i. CLIENTSHIP, DELEGATION AND iNHERITANCE

Clientship, delegation and inheritance are three mechanisms for sharing knowledge amorg related objects in object oriented languages.

Inheritance implements the set-theoretic approach. It is based on the concepts of class and instance. A class collects objects according to their "type", encoding their common behavior and declaring a set of variables that each of its instances must have but with individual values. Instances can share ~thods but not values. Inheritance allows incremental definition o~ classes but not of instances, since they cannot be defined directly in terms one of another.

Delegation implements the concrete approach. It removes the notion of "type" ~bjez~ and

introduces that of prototype. ~very object can serve as a prototype, and thus it describes the default behavior for a concept. New objects can share part of the knowledge stored in the prototype by saying how they differ from it. Objects can share both methods and variables. Delegation allows incremental definition of all objects, They can be directly defined in terms

one of another.

The two mechanisms differ not only in how they structure objects bu~ also in the way they i~plement the method lookup. In delegation it is accomplished through message-passlng. If an object has no local method for replying to a message, it forwards the message to its prototypes. In inheritance the method lookup

is performed by a primLtive, unchangeable routine. It is easy to see that delegation can implement the functionality of inheritance, but there is not agreement that the opposite is true. The special variable s~If represents a

reference to the object that "orlqinaliJ' received the message [2]. With inherlt,;~:E, every time a message is forwarded the self variable is re-bound, so that it is impossible for an object to reply in place of the object which originally received the message. It is not so in delegation, where forwarding a message does not cause the re-bounding of the

self variable. Lieberman [2] uses this argument in order to prove that inheritance

cannot capture the behavior of delegation so that he argues that delegation is more powerful than inheritance. Stein [3) asserts that the two mechanisms are substantially equivalent. Looking at models like that of Smalltalk [where classes are objects too, because they can have attributes of their own), Stein [3] observes that class inheritance {"is-a" relationship) cannot be interpreted other than delegation of class attributes and shows a formal model where prototypes are mapped into classes. However, in languages where classes are pure types, the approach of Stein [3] is not applicable. A more recent study [4] concludes that inheritance and delegation (sh~ring protocols) are orthogonal with the concepts of class and prototype (organization protocol) and demonstrates that inheritance "has a fundamental speed advantage over delegation in most situations, and that the speed and space

optimizations possible for class-based systems usually outweigh the need fo~ the sharing

18 P. Nieddu

flexibility protot!rpe-based systems offer". The present approach takes positions very similar to those in what concerns the implementabive problems of the work, even though it adopts a more traditional point of view.

Data abstraction and encapsulation (two topics of object oriented programming) can be realized through the concept of module. A module is a separate program unit whose interface works as a syntactic "membrane" which controls the visibility (from otler modules) of entities embodied into tbe mudule. When analyzing features of inheritance: and clientship, several ways in which the two mechanisms differ can be pointed out, i.e.: (i) Semantic role A class is a particulac kind of type. A module

does nob denote any s~nantic entity. (2) Operational role A modale can be viewed as an object (even if it is not a first-class entity) while a class cannot (at least in strongly typed languages where it is a pure type). (3) Attribute acquisition Inherited attributes are automatically parts of the heir's protocol. This does not happen with ,lientship. (4] Late binding polimorphism inherited virtual methods implement late binding polim~rphism, clientship does not know this concept. 15) Subtyping Inheritance hierarchies are subtype hierarchies while clientship hierarchies are not. 16) Software decentralization inheritance allows it while clientship does not. (7) Extensibility Inheritance allows an object to be extended without recompiling it. A mudule is extendible only through recompilation.

There are strong differences also between delegation and inheritance, but a kind of simil~rity too. R module can be viewed as an object. But while its clienns can use only a static version of the services exported by the =~dule, with delegation that version can be virtual.

2. A UNIFYING APPROACH

The point of view adopted in this work is the following: the activation environment of the attired attribute distinguishes among the mechanisms. I~ is fully determined by the client object in inheritance, statically by the supplier object in clientship, and by both objects in delegation.

The possibility of unifying the three mechanisms into a single construct has been studied. A similar approach is discussed by

Stein [3] who stresse~ its practical importance

too. Among inheritance based languages, strongly typed ones have received a special attention in order to make ~he cumparison of the three mechanisms on a strongly typed basis. The treatment of subtyping has been taken from Cardelli [i],

An acquiring mechanism inspired to the import/export facilities offered by modular languages has been introduced into a hypothetical traditional environment based on objects and simil~r to the prototype-based delegation one. It realizes a generalized form of delegation which ranges from the simple client relation to a form of inheritance. Chiefly semantic considerations have induced to consider such a mechanism as a pure code sharing tool, at least in this early stage of the work. A client can selectively acquire a service from a supplier. If that acquisition is specified as clientship, then the service will be valued into an environment which is fully determined by the supplier (concept1~a!ly, the method is mapped into the environment o? the supplier where it executes the appropriate operations). If the acquisition is specified as delegation, then the service will be valued into the supplier's environment eventually

modified by the client (a combination of both environments, the supplier and the client one). If it is specified as inheritance, then the environment will be fully determined by the client. Here the syntax is simply sketched. In its generic form, it is inspired te the Module-2 one.

AcqList ::= {"FROM" ObjName Acq {"," Acq} ";"} Acq ::= "IMP" HetbodName IRenaming]

"DEL" MethodName (Renaming] "INH" MethodName [Renamingl "NEW" MethodName [Renaming]

As far as the data model is concerned, it is immediate to verify that this construct allows ts obtain all the functionalities both of delegation and inheritance in their classic semantics. The results relative to the analysis of acquisition chains can be suJ~arized as follow: clientship is the strongest among the three mechanisms followed

by inheritance and then by delegation. The degree of strength of a mechanism is measured in terms of how much specifications subsequent to the acquisition of a method according to that mechanism affect the activation environment of the method.

Difficult problems appear on the implementative ground in studying an operational semantics for the mechanism, where the aim is that of reaching a reasonably good compromise between expressive power and implementation efficiency on speed and space. Such problems can be su~arized as follow: (l} Variable access With inheritance, "virtuality" (according to the meaning this term has in C++) is a

A unilying approach to clientship in object oriented languages 17

characteristic only of methods. With delegation is both of methods and variables. This affects the optimization techniques for variable access which are peculiar of inheritance. {2) Object structure While the structure of a child class is pertly isomorphic to that of its parent class, the structure of a delegating object can be very different from that of its prototypes. This affects the possibility of exploiting fixed offsets in determining relative addresses and solving references at compile time. Such considerations affect software reusability. (3) Self binding It is very different in delegation and inheritance, so it is hard to modify the two in order to unify them. (4) Z~itiple acquisition Problems are not only of semantic nature (which choice to do) but mostly of implementative n~t~we (how to make this choice possible with reasonable space consume). Acquisition can he multiple (from mor~ than one object) under unique mode (cl}ontship aut delegation aut inheritance), multiple under multiple mode, single under multiple mode etc., and even acquiring from a single object but under different modes is substantially the same as acqui/ing from different objects because the activation environments involved can be quite different. That can have unpleasant conseguen~es if a copy strategy, llke that of multiple inheritance, is adopted. (5) Selectivity Selectivity is introduced in order to increase softwa~ reusability but is also a further complication of the object structure problem. (6) Compatibility Type compatibility is not structural

compatibility but behavioral compatibility.

The way objects are structured is of great importance when considereg together with the way the method lookup is implemented.

It is possible to take a prototype-based delegation-like model where objects have locally only attributes they explicitly acquired and where the method lookup is accomplished through message-passing.

With such an approach, the great problem is selectivity. The outermost self strategy is incapable of solving this situation because it does not assure the capability to go up the acquisition chain (the client does not acquire everything from the supplier so that it possesses references to the supplier's attributes rather than to the supplier itself) or to do it correctly semantic problems similar to the traditional multiple inheritance ones).

A solution is that of adopting a strategy similar to the one called "four-phase protocol" and described in (4]. Once the

object defining the method is found, all the attributes required by the m ~ t h o d are gathered in one pass in a descriptor and returned to

that object, and only after the appropriate computation is carried out. To be precise, if the attribute is a variable the descriptor contains its address, while if it is a method it contains a pointer to the object frc~n which the method lookup must begin.

This approach guarantees a certain speed in computation because of the f i x e d structure on which the code of the method has to work. H~sver, the critical points are represented by the size and the number of the descriptors and by the attribute searching phase as well. In order to check if an object has one of the attributes required by the descriptor, every attribute of that object must be examined,

because generally there is no structural

isomorphism between that object and tbe descriptor (that is between the object which is now considered and that in which the body of the method is defined) capable of ensuring that, in that object, that attribute has the specified offa~t or no offset at a11. Such run-time searching operations can he assumed to

be of negligible cost only if the size of the objects is quite small, and this is not always the case since it depends on specific dcm,ains of application and users" choices.

The opposite technique is inspir~ uo the copy strategy peculiar of inheritance (where each object is completely self-contained) espaclaily in strongly typed languages. By copying into the client all information it needs (in hidden form if necessary), by realizing, whenever possible, the transitive closure of acquisition chains, by using method tables and appropriate techniques (taking as a starting point those for multiple inheribance) in order to solve relatlve references at compile bim~, and eventually by introducing static methods, the method lookup seems to he solvable in constant time through tables. Here, a greater speed is obtained paying a generally higher cost in space. In this way a structural isomo:phism among related objects is recovered. It is only partial, and two isomorphic parts of two different objects can be in different points at different depths inside them, but that is enough to avoid run-time attribute searching. For example, a base passed as one of the method's parameters could specify where in the object (that received the message) is the method's environment, that is o n which attributes the computation must be carried out, and after that there isn't any more problem because offsets are fixed.

The current prototype implementation follows this way. It is n o t possible to be more precise about costs until a deeper study is done. However powerful architectures, like the 32000 or 68000 ones, give good hopes about the implementative meaning of this approach, for

18 P. Nieddu

they would pe~it to speed up the passage through all the indirect references (certainly more than two) needed to find an attribute, qathering them in a fewer number of machine addressing operations.

It ~ouldbe al~o possible to adopt specific approches according to particular interests in applications. FOr example, especially in a distributed environment the following implementativ~ s~rategy seems useful. The compile= copies down the compiled code of the acquired method into the client object and reprocessing it fits the virtual references on the specific case. But if the aim is to quarantee flexibility, the model can i~lement inheritance from static structure but clientship and delegation from fully dynamic ones that during different time in execution can have different structure. Obviously, all this sacrifices speed. The study of these alternatives will be the subject oZ future work, together wlth the analysis of problems a~ou~ the 8emantlcs and the implementation of a typed delegation concept.

The study about unification of clientship, inheritanc@ and deleqation points out great disagreements among the three mechanisms. However, it seems that tracing appropriate

limits to the potentialities of the three and automating more the operations on acquisition chains it is possible to reach interesting results not only on th~ theoretical ground but also on the practical ane.

ACKNOWLEDGEMENTS

J would like to thank Massimo Anco.a for helping me during my thesis work the topic of which has become the subject of this paper.

REFERENCES

[i] Cardelli, L. and Weqner, P.~ On Understanding Types, Data Abstraction, and Polymorphism, Computing Surveys (1985) 17(4) pp. 471-522

[2] Lieberman, H., Using !rototypica] Objects to Implement Shared Behavior Iz. object Oriented System, in: COPSLA "86 Proceedings (1986] pp. 214-223

[2) Stein, L.A., Delegation Is Inheritance, in: OOPSLA '87 Proceedings (1987) pp. 138-146

[4] Tomlinson, C., Scheevel, M. and Kim, W., Sharing and Organization Protocols in Object-Oriented Systems, JOOP (November/December 1989) pp. 25-36