Presentation is loading. Please wait.

Presentation is loading. Please wait.

“Traits: Composable Units of Behavior” N. Schaerli, S. Ducasse, O. Nierstrasz, and A. Black, U Bern / OHSU, ECOOP 2003 “Traits: A Mechanism for Fine-grained.

Similar presentations


Presentation on theme: "“Traits: Composable Units of Behavior” N. Schaerli, S. Ducasse, O. Nierstrasz, and A. Black, U Bern / OHSU, ECOOP 2003 “Traits: A Mechanism for Fine-grained."— Presentation transcript:

1 “Traits: Composable Units of Behavior” N. Schaerli, S. Ducasse, O. Nierstrasz, and A. Black, U Bern / OHSU, ECOOP 2003 “Traits: A Mechanism for Fine-grained Reuse” S. Ducasse, O. Nierstrasz, N. Schaerli, R. Wuyts, and A. Black, ACM TOPLAS (forthcoming) Presented by Evgeniy Gabrilovich Traits Traits are primitive units of code reuse that consist only of methods (i.e., no state)

2 The quest for better reuse mechanisms Common forms of inheritance –Single / multiple / mixin inheritance Limitations of the different forms of inheritance Traits, traits, traits … –Introduction to traits –Usage examples –Discussion of trait properties –Implementation Smalltalk-80, Scala, C#/Rotor, Perl 6 (“roles”)

3 Key observation about reuse A class is not necessarily an appropriate element of reuse Two contradictory roles of classes –Generator of instances  A class must be complete  Each class should have a unique place in the class hierarchy –Unit of reuse  A class should be small  Units of reuse should be applicable at numerous arbitrary places

4 Single inheritance Not expressive enough for factoring out common features shared by classes in a complex hierarchy –Code duplication Smalltalk example ReadStreamWriteStream ReadWriteStream ? ReadStreamWriteStream ReadWriteStream Code duplication PositionableStream read + write functions

5 “Multiple inheritance is good, but there is no good way to do it” (Steve Cook, OOPSLA’87) Problem #1: Conflicting features that are inherited along different paths –Conflicting methods Can be resolved by overriding –Conflicting state variables A B D C

6 Problem #2: Limited compositional power A read write: B read write: A read write: SyncA read write: acquireLock releaseLock read self acquireLock res := super read self releaseLock ^ res write: val self acquireLock super write: val self releaseLock SyncReadWrite read write: acquireLock releaseLock SyncASyncB 

7 Multiple inheritance example in C++: base class with abstract methods class SyncReadWrite { public: virtual int read() { acquireLock(); result = directRead(); releaseLock(); return result; } virtual void write(int n) { acquireLock(); directWrite(n); releaseLock(); } protected: virtual void acquireLock() { // acquire lock } virtual void releaseLock() { // release lock } virtual int directRead() = 0; virtual void directWrite(int n) = 0; }; // end of class SyncReadWrite

8 Multiple inheritance example in C++: code duplication in child classes class SyncA : public A, SyncReadWrite { public: virtual int read() { return SyncReadWrite::read(); } virtual void write(int n) { SyncReadWrite::write(n); } protected: virtual int directRead() { return A::read(); } virtual void directWrite(int n) { A::write(n); } }; // end of class SyncA class SyncB : public B, SyncReadWrite { public: virtual int read() { return SyncReadWrite::read(); } virtual void write(int n) { SyncReadWrite::write(n); } protected: virtual int directRead() { return B::read(); } virtual void directWrite(int n) { B::write(n); } }; // end of class SyncB Code duplication

9 Let’s mix it! A mixin is an (abstract subclass) specification –may be applied to various classes to extend them with the same set of features Key idea: create components designed for reuse rather than for instantiation Implementation –C++ – using templates –Java – using (multiple inheritance of) interfaces –Smalltalk – language extension using a mixin invocation operator

10 Mixin example Rectangle asString ^ super asString, ‘ ‘, self color asString Rectangle + MColor asString serializeOn: MColor asString serializeOn: Rectangle + MColor + MBorder asString serializeOn: MyRectangle asString ^ super asString, ‘ ‘, self borderWidth asString MBorder asString serializeOn:

11 Mixins are not a panacea Problems? You bet! –It is impossible to control how individual features are composed –Composition of mixins is messy Mixins applied later in the chain (silently) override identically named features of earlier mixins Reestablishing the original behavior requires changes in other mixins –Modifying a mixin used in several places in a class hierarchy may be particularly unpleasant

12 Mixins in C++: no multiple inheritance template class MSyncReadWrite : public Super { public: virtual int read() { acquireLock(); result = Super::read(); releaseLock(); return result; } virtual void write(int n) { acquireLock(); Super::write(n); releaseLock(); } protected: virtual void acquireLock() { // acquire lock } virtual void releaseLock() { // release lock } }; // end of MSyncReadWrite class SyncA : public MSyncReadWrite {}; class SyncB : public MSyncReadWrite {};

13 Introduction to traits Lightweight software components –Basic building blocks for classes –Primitive units of code reuse A trait provides methods that implement behavior A trait requires methods that parameterize the provided behavior (optional) –Required methods are used by – not implemented in – a trait

14 Sample traits TCircle = hash < <= … area bounds circumference scaleBy: … center center: radius radius: TDrawing draw refresh refreshOn: bounds drawOn: Geometry-related behaviorDrawing-related behavior

15 Sample trait implementation in (an extension of) Smalltalk Trait named: #TDrawing uses: {} draw ^ self drawOn: World canvas refresh ^ self refreshOn: World canvas refreshOn: … bounds self requirement drawOn: aCanvas self requirement

16 Trait composition Classes are composed from traits –Provide required methods –Resolved conflicts due to trait composition Traits can be nested –The semantics for the containing class is not nested –Traits are inlined Nested traits are equivalent to flattened traits

17 Addressing known problems Traits specify no state –Methods provided by traits never access state variable directly Only using required methods –Can only cause method conflicts Can be resolved by overriding or by exclusion Traits are detached from the inheritance hierarchy Traits are not composed in any particular order

18 Class = Superclass + State + Traits + Glue methods TCircle = hash < <= … area bounds circumference scaleBy: … center center: radius radius: TDrawing draw refresh refreshOn: bounds drawOn: Circle initialize drawOn: center center: radius radius:

19 Sample class using traits Object subclass: #Circle instanceVariableNames: ‘center radius’ traits: {TCircle. TDrawing} initialize center := 0@0. radius := 50 center ^ center radius ^ radius drawOn: aCanvas … center: aPoint center := aPoint radius: aNumber radius := aNumber

20 Completing a class definition In order for a class to be complete, all the requirements of the traits must be satisfied These methods can be implemented –in the class itself, –in a direct or indirect superclass, –by another trait that is used by the class.

21 The flattening property The semantics of a method defined in a trait is identical to the semantics of the same method defined in a class that uses the trait. –The keyword super has no special semantics for traits –super simply refers to the superclass of the class that uses the trait.

22 Nested traits TCircle < = hash TGeometry area bounds scaleBy: … center center: radius radius: TMagnitude <= > between:and: < TEquality ~== hash

23 Flattened nested traits TCircle < = hash area bounds scaleBy: … center center: radius radius: <= > between:and: ~=

24 More nested traits TEquality ~== hash TColor red green saturation red: … = hash rgb rgb:

25 Lack of composition order The order of trait composition is irrelevant  Conflicting trait methods must be explicitly disambiguated Precedence rules for conflict resolution –Class methods take precedence over trait methods (= overriding trait methods) –Traits methods take precedence over superclass methods (flattening property!)

26 Method conflicts TCircle = hash ~= … area bounds circumference scaleBy: … center center: radius radius: TDrawing draw refresh refreshOn: bounds drawOn: Circle initialize = hash rgb rgb: drawOn: center center: radius radius: TColor = hash ~= red … rgb rgb: TEquality ~== hash

27 traits: { TCircle @ { #circleHash -> #hash. #circleEqual: -> #= } } Conflict resolution Conflicts must be explicitly resolved –Conflicting methods are excluded, and turned into required ones Possible ways to resolve a conflict: –Define an overriding method in the class or in the composite trait –Rename conflicting methods (aliasing) –Avoid a conflict by explicitly excluding some methods traits: { TCircle. TDrawing. TColor - { #=. #hash. #~=. } }

28 C++ Revisited Document MSyncReadWrite > MLogOpenClose MyDocument Document TLogOpenClose MyDocument TSyncReadWrite virtual

29 Traits in C++ template class TLogOpenClose : virtual public Super { public: virtual void open() { … } virtual void close() { … } virtual void reset() { … } protected: virtual void log(const char* s) { … } }; // end of TLogOpenClose template class TSyncReadWrite : virtual public Super { public: virtual void read() { … } virtual void write(int n) { … } virtual void reset() { … } protected: virtual void acquireLock() { … } virtual void releaseLock() { … } }; // end of TSyncReadWrite class MyDocument : public TLogOpenClose, public TSyncReadWrite { … // glue code };

30 Traits in C++: what we can and cannot do Nested traits template class TLogAndSync : virtual public TLogOpenClose, virtual public TSyncReadWrite { }; Composition of traits –Sum … OK –Aliasing … can be simulated using scope operator :: –Exclusion … nope  Every conflict must be resolved by overriding the conflicting methods

31 Review of trait properties Untangling reusability and classes –Classes are instance generators and hence have to be complete –Units of reuse should be small Trait composition operates at a finer granularity than inheritance –Single inheritance is retained –Flattening property Conflicting features –Methods only, no state –If the same method from the same trait is obtained via multiple paths, there is no conflict

32 Evaluation against identified problems: code duplication Stream position position: WriteStream nextPut: position: ReadStream next ReadWriteStream next Code duplication

33 Stream hierarchy refactored using traits Stream position position: WriteStreamReadStream ReadWriteStream TReadStream TWriteStream

34 Evaluation against identified problems: duplicated wrappers Like mixins, traits can explicitly refer to a method implemented by the superclass B read write: A read write: SyncReadWrite read write: acquireLock releaseLock SyncASyncB  TSyncReadWrite read write: acquireLock releaseLock read write: A read write: SyncA

35 Mixin example (revisited) Rectangle asString ^ super asString, ‘ ‘, self color asString Rectangle + MColor asString serializeOn: MColor asString serializeOn: Rectangle + MColor + MBorder asString serializeOn: MyRectangle asString ^ super asString, ‘ ‘, self borderWidth asString MBorder asString serializeOn:

36 Evaluation against identified problems: composition Total ordering –Trait composition does not impose total ordering Dispersal of glue code –Glue code is always located in the combining entity The superordinate entity is in complete charge of plugging together the components that implement its features –Glue code is separated from the implementation of features

37 Traits offer more control Rectangle asString MyRectangle TColor asString serializeOn: TBorder asString serializeOn: Glue code

38 Evaluation against identified problems: fragile hierarchies Every method conflict must be resolved explicitly –This requires extra work … but you always get what you expect Changes mandated by conflict resolution are limited to the direct users of the trait –A direct client can simply exclude a new trait method Not so with mixins –introducing a new method may require changes to many other components or addition of new components


Download ppt "“Traits: Composable Units of Behavior” N. Schaerli, S. Ducasse, O. Nierstrasz, and A. Black, U Bern / OHSU, ECOOP 2003 “Traits: A Mechanism for Fine-grained."

Similar presentations


Ads by Google