[Pharo-project] Traits composition question
Suppose i having a trait grouping Trait named: #TraitGroup uses: TraitA + TraitB + .... TraitN category: 'foo' and suppose i want to use TraitGroup in one of my classes, but excluding one of the traits in the list above.. i.e. something like: Object subclass: #Myclass uses: TraitGroup - TraitA .. but the above code don't seem to work.. Any clues, how i can do that? Is such kind of composition possible at all? -- Best regards, Igor Stasenko AKA sig.
No, this is not possible. You can only exclude single methods but not whole traits. Adrian On Oct 25, 2009, at 06:37 , Igor Stasenko wrote:
Suppose i having a trait grouping
Trait named: #TraitGroup uses: TraitA + TraitB + .... TraitN category: 'foo'
and suppose i want to use TraitGroup in one of my classes, but excluding one of the traits in the list above.. i.e. something like:
Object subclass: #Myclass uses: TraitGroup - TraitA ..
but the above code don't seem to work.. Any clues, how i can do that? Is such kind of composition possible at all?
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
2009/10/25 Adrian Lienhard <adi@netstyle.ch>:
No, this is not possible. You can only exclude single methods but not whole traits.
Too bad, specifying dozens of methods for exclusion is not very funny :)
Adrian
On Oct 25, 2009, at 06:37 , Igor Stasenko wrote:
Suppose i having a trait grouping
Trait named: #TraitGroup uses: TraitA + TraitB + .... TraitN category: 'foo'
and suppose i want to use TraitGroup in one of my classes, but excluding one of the traits in the list above.. i.e. something like:
Object subclass: #Myclass uses: TraitGroup - TraitA ..
but the above code don't seem to work.. Any clues, how i can do that? Is such kind of composition possible at all?
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
Hi Igor,
Trait named: #TraitGroup uses: TraitA + TraitB + .... TraitN category: 'foo'
and suppose i want to use TraitGroup in one of my classes, but excluding one of the traits in the list above.. i.e. something like:
Object subclass: #Myclass uses: TraitGroup - TraitA ..
but the above code don't seem to work.. Any clues, how i can do that?
The exclusion is specified between a trait and a set of selectors, not between two traits. You need to write for example:
Object subclass: #Myclass uses: TraitGroup - {#m1 . #m2}
If #m1 and #m2 are two methods of TraitA (i.e., defined on or acquired by TraitA). Cheers, Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
2009/10/26 Alexandre Bergel <alexandre@bergel.eu>:
Hi Igor,
Trait named: #TraitGroup uses: TraitA + TraitB + .... TraitN category: 'foo'
and suppose i want to use TraitGroup in one of my classes, but excluding one of the traits in the list above.. i.e. something like:
Object subclass: #Myclass uses: TraitGroup - TraitA ..
but the above code don't seem to work.. Any clues, how i can do that?
The exclusion is specified between a trait and a set of selectors, not between two traits.
You need to write for example:
Object subclass: #Myclass uses: TraitGroup - {#m1 . #m2}
If #m1 and #m2 are two methods of TraitA (i.e., defined on or acquired by TraitA).
Yes, i know Alex. And this is awkward , because i can't control composition _indirectly_ , only directly. The problem i want to solve is following: A base trait (BaseTrait) provides a protocol , which implies accessing/using some state. This means, that trait having all methods which potential class would have, including accessors. But accessors is implemented as: 'self shouldBeImplemented'. In this way, i creating an error-proof and self-documenting trait , because developer could clearly see what methods should be overridden in a class which using the trait. Now for this trait, i creating a basic class, which implemets necessary methods by overriding some trait methods. Object subclass: #MyBase uses: BaseTrait now if i make a subclass of it, MyBase subclass: #NextClass i know, that its already implementing a protocol of BaseTrait. However, i want to add more things to it, because i having a: Trait named: #CompositeTrait uses: BaseTrait + TraitA + TraitB + ... Next, i want to reuse the MyBase behavior by inheritance, and CompositeTrait by using it: Mystate subclass: #NextClass uses: CompositeTrait But here the problem: if i apply CompositeTrait, it will override all of the BaseTrait methods again, leaving no way how i can reuse the MyBase class methods, unless i'm explicitly specify all protocol of BaseTrait for exclusion.. Which is really awkward. Just compare this: Mystate subclass: #NextClass uses: CompositeTrait - {#foo. #bar. #baz. ....... a list could be very long } and this: Mystate subclass: #NextClass uses: CompositeTrait - BaseTrait moreover, whenever i change the BaseTrait protocol, i would need to revisit the NextClass declaration again and again, instead of doing nothing :( Of course, you could say that solution is to not include the BaseTrait in CompositeTrait at first place. But i indend to do so, because in this way i'm clearly stating what interfaces the class should support, otherwise the only way how i would tell developer to not forget to include BaseTrait is write in CompositeTrat comment: 'Hey, pal, if you want to use thit trait, make sure that your class implements the BaseTrait protocol'. :) Of course, these problems would go away if we could afford stateful traits(aka mixins).. Then really, there would be no need to use a class inheritance, and all classes could be composed from traits having an Object class as base class. But until then, i need to use some tricks , to deal with state.
Cheers, Alexandre
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel  http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
I recognized the issue we had with 'self explicitRequirement'. Methods acquired by a trait override methods defined in superclasses. This is the behavior everyone expect. However, when a method is used for a purpose different than defining functional behavior, then unwanted effect emerge. For traits, requirements were programmatically inferred instead of using #explicitRequirement. Hope it helps, Alexandre On 26 Oct 2009, at 13:41, Igor Stasenko wrote:
2009/10/26 Alexandre Bergel <alexandre@bergel.eu>:
Hi Igor,
Trait named: #TraitGroup uses: TraitA + TraitB + .... TraitN category: 'foo'
and suppose i want to use TraitGroup in one of my classes, but excluding one of the traits in the list above.. i.e. something like:
Object subclass: #Myclass uses: TraitGroup - TraitA ..
but the above code don't seem to work.. Any clues, how i can do that?
The exclusion is specified between a trait and a set of selectors, not between two traits.
You need to write for example:
Object subclass: #Myclass uses: TraitGroup - {#m1 . #m2}
If #m1 and #m2 are two methods of TraitA (i.e., defined on or acquired by TraitA).
Yes, i know Alex.
And this is awkward , because i can't control composition _indirectly_ , only directly.
The problem i want to solve is following:
A base trait (BaseTrait) provides a protocol , which implies accessing/using some state. This means, that trait having all methods which potential class would have, including accessors. But accessors is implemented as: 'self shouldBeImplemented'. In this way, i creating an error-proof and self-documenting trait , because developer could clearly see what methods should be overridden in a class which using the trait. Now for this trait, i creating a basic class, which implemets necessary methods by overriding some trait methods.
Object subclass: #MyBase uses: BaseTrait
now if i make a subclass of it,
MyBase subclass: #NextClass
i know, that its already implementing a protocol of BaseTrait.
However, i want to add more things to it, because i having a:
Trait named: #CompositeTrait uses: BaseTrait + TraitA + TraitB + ...
Next, i want to reuse the MyBase behavior by inheritance, and CompositeTrait by using it:
Mystate subclass: #NextClass uses: CompositeTrait
But here the problem: if i apply CompositeTrait, it will override all of the BaseTrait methods again, leaving no way how i can reuse the MyBase class methods, unless i'm explicitly specify all protocol of BaseTrait for exclusion.. Which is really awkward. Just compare this:
Mystate subclass: #NextClass uses: CompositeTrait - {#foo. #bar. #baz. ....... a list could be very long }
and this:
Mystate subclass: #NextClass uses: CompositeTrait - BaseTrait
moreover, whenever i change the BaseTrait protocol, i would need to revisit the NextClass declaration again and again, instead of doing nothing :(
Of course, you could say that solution is to not include the BaseTrait in CompositeTrait at first place. But i indend to do so, because in this way i'm clearly stating what interfaces the class should support, otherwise the only way how i would tell developer to not forget to include BaseTrait is write in CompositeTrat comment: 'Hey, pal, if you want to use thit trait, make sure that your class implements the BaseTrait protocol'. :)
Of course, these problems would go away if we could afford stateful traits(aka mixins).. Then really, there would be no need to use a class inheritance, and all classes could be composed from traits having an Object class as base class. But until then, i need to use some tricks , to deal with state.
Cheers, Alexandre
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
2009/10/26 Alexandre Bergel <alexandre@bergel.eu>:
I recognized the issue we had with 'self explicitRequirement'. Methods acquired by a trait override methods defined in superclasses. This is the behavior everyone expect. However, when a method is used for a purpose different than defining functional behavior, then unwanted effect emerge.
Right.
For traits, requirements were programmatically inferred instead of using #explicitRequirement.
Not sure i understood. Is there a way to tell to not override the method automatically, if it provided in base class?
Hope it helps, Alexandre
On 26 Oct 2009, at 13:41, Igor Stasenko wrote:
2009/10/26 Alexandre Bergel <alexandre@bergel.eu>:
Hi Igor,
Trait named: #TraitGroup uses: TraitA + TraitB + .... TraitN category: 'foo'
and suppose i want to use TraitGroup in one of my classes, but excluding one of the traits in the list above.. i.e. something like:
Object subclass: #Myclass uses: TraitGroup - TraitA ..
but the above code don't seem to work.. Any clues, how i can do that?
The exclusion is specified between a trait and a set of selectors, not between two traits.
You need to write for example:
Object subclass: #Myclass uses: TraitGroup - {#m1 . #m2}
If #m1 and #m2 are two methods of TraitA (i.e., defined on or acquired by TraitA).
Yes, i know Alex.
And this is awkward , because i can't control composition _indirectly_ , only directly.
The problem i want to solve is following:
A base trait (BaseTrait) provides a protocol , which implies accessing/using some state. This means, that trait having all methods which potential class would have, including accessors. But accessors is implemented as: 'self shouldBeImplemented'. In this way, i creating an error-proof and self-documenting trait , because developer could clearly see what methods should be overridden in a class which using the trait. Now for this trait, i creating a basic class, which implemets necessary methods by overriding some trait methods.
Object subclass: #MyBase uses: BaseTrait
now if i make a subclass of it,
MyBase subclass: #NextClass
i know, that its already implementing a protocol of BaseTrait.
However, i want to add more things to it, because i having a:
Trait named: #CompositeTrait uses: BaseTrait + TraitA + TraitB + ...
Next, i want to reuse the MyBase behavior by inheritance, and CompositeTrait by using it:
Mystate subclass: #NextClass uses: CompositeTrait
But here the problem: if i apply CompositeTrait, it will override all of the BaseTrait methods again, leaving no way how i can reuse the MyBase class methods, unless i'm explicitly specify all protocol of BaseTrait for exclusion.. Which is really awkward. Just compare this:
Mystate subclass: #NextClass uses: CompositeTrait - {#foo. #bar. #baz. ....... a list could be very long }
and this:
Mystate subclass: #NextClass uses: CompositeTrait - BaseTrait
moreover, whenever i change the BaseTrait protocol, i would need to revisit the NextClass declaration again and again, instead of doing nothing :(
Of course, you could say that solution is to not include the BaseTrait in CompositeTrait at first place. But i indend to do so, because in this way i'm clearly stating what interfaces the class should support, otherwise the only way how i would tell developer to not forget to include BaseTrait is write in CompositeTrat comment: 'Hey, pal, if you want to use thit trait, make sure that your class implements the BaseTrait protocol'. :)
Of course, these problems would go away if we could afford stateful traits(aka mixins).. Then really, there would be no need to use a class inheritance, and all classes could be composed from traits having an Object class as base class. But until then, i need to use some tricks , to deal with state.
Cheers, Alexandre
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel  http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel  http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
this is an implementation bug we should once fix.
2009/10/26 Alexandre Bergel <alexandre@bergel.eu>:
I recognized the issue we had with 'self explicitRequirement'. Methods acquired by a trait override methods defined in superclasses. This is the behavior everyone expect. However, when a method is used for a purpose different than defining functional behavior, then unwanted effect emerge.
Right.
For traits, requirements were programmatically inferred instead of using #explicitRequirement.
Not sure i understood. Is there a way to tell to not override the method automatically, if it provided in base class?
Hope it helps, Alexandre
On 26 Oct 2009, at 13:41, Igor Stasenko wrote:
2009/10/26 Alexandre Bergel <alexandre@bergel.eu>:
Hi Igor,
Trait named: #TraitGroup uses: TraitA + TraitB + .... TraitN category: 'foo'
and suppose i want to use TraitGroup in one of my classes, but excluding one of the traits in the list above.. i.e. something like:
Object subclass: #Myclass uses: TraitGroup - TraitA ..
but the above code don't seem to work.. Any clues, how i can do that?
The exclusion is specified between a trait and a set of selectors, not between two traits.
You need to write for example:
Object subclass: #Myclass uses: TraitGroup - {#m1 . #m2}
If #m1 and #m2 are two methods of TraitA (i.e., defined on or acquired by TraitA).
Yes, i know Alex.
And this is awkward , because i can't control composition _indirectly_ , only directly.
The problem i want to solve is following:
A base trait (BaseTrait) provides a protocol , which implies accessing/using some state. This means, that trait having all methods which potential class would have, including accessors. But accessors is implemented as: 'self shouldBeImplemented'. In this way, i creating an error-proof and self-documenting trait , because developer could clearly see what methods should be overridden in a class which using the trait. Now for this trait, i creating a basic class, which implemets necessary methods by overriding some trait methods.
Object subclass: #MyBase uses: BaseTrait
now if i make a subclass of it,
MyBase subclass: #NextClass
i know, that its already implementing a protocol of BaseTrait.
However, i want to add more things to it, because i having a:
Trait named: #CompositeTrait uses: BaseTrait + TraitA + TraitB + ...
Next, i want to reuse the MyBase behavior by inheritance, and CompositeTrait by using it:
Mystate subclass: #NextClass uses: CompositeTrait
But here the problem: if i apply CompositeTrait, it will override all of the BaseTrait methods again, leaving no way how i can reuse the MyBase class methods, unless i'm explicitly specify all protocol of BaseTrait for exclusion.. Which is really awkward. Just compare this:
Mystate subclass: #NextClass uses: CompositeTrait - {#foo. #bar. #baz. ....... a list could be very long }
and this:
Mystate subclass: #NextClass uses: CompositeTrait - BaseTrait
moreover, whenever i change the BaseTrait protocol, i would need to revisit the NextClass declaration again and again, instead of doing nothing :(
Of course, you could say that solution is to not include the BaseTrait in CompositeTrait at first place. But i indend to do so, because in this way i'm clearly stating what interfaces the class should support, otherwise the only way how i would tell developer to not forget to include BaseTrait is write in CompositeTrat comment: 'Hey, pal, if you want to use thit trait, make sure that your class implements the BaseTrait protocol'. :)
Of course, these problems would go away if we could afford stateful traits(aka mixins).. Then really, there would be no need to use a class inheritance, and all classes could be composed from traits having an Object class as base class. But until then, i need to use some tricks , to deal with state.
Cheers, Alexandre
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
For traits, requirements were programmatically inferred instead of using #explicitRequirement.
In the original traits implementation, inference of requirements was necessarily incomplete. For example, if a method says self add: x or self class new: n we would infer a requirement of add: n the instance side and new: on the class side. However, if the method said self copyEmpty add: x we would not infer a requirement of add: In these cases we included a method definition add: anObject self explicitRequirement to tell the tools that add: was a required method. We used this very rarely, since most of the time the inference of required methods worked very well. Andrew
For traits, requirements were programmatically inferred instead of using #explicitRequirement.
Not sure i understood.
Is it really necessary that you provides 'self shouldBeImplemented' as method body?
Is there a way to tell to not override the method automatically, if it provided in base class?
No that I know. But this goes against the idea of Traits. A class that uses a trait is rigorously equivalent to having the class implements the methods defined in the trait. As a consequence, if you trait defines a method 'foo self shouldBeImplemented' and your class C uses the trait, then 'C new foo' will execute 'self shouldBeImplemented', independently whether #foo was implemented or not in superclasses of C. Cheers, Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
2009/10/26 Alexandre Bergel <alexandre@bergel.eu>:
For traits, requirements were programmatically inferred instead of using #explicitRequirement.
Not sure i understood.
Is it really necessary that you provides 'self shouldBeImplemented' as method body?
yes, it is. :) Trait , in this case covers the protocol without any gaps. Which is good from design perspective i think, because developer who never dealt with given trait before, could easily see what he should care about. Doing otherwise, you leaving him clueless and stealing his time, which he will spend on (re)discovering the complete necessary behavior when using this trait.
Is there a way to tell to not override the method automatically, if it provided in base class?
No that I know. But this goes against the idea of Traits. A class that uses a trait is rigorously equivalent to having the class implements the methods defined in the trait. As a consequence, if you trait defines a method 'foo  self shouldBeImplemented' and your class C uses the trait, then 'C new foo' will execute 'self shouldBeImplemented', independently whether #foo was implemented or not in superclasses of C.
I disagree. It doesn't. You already can exclude the trait's methods from composition, but only explicitly and in direct way. What i'm wanting is to have more flexible & little bit indirect way i.e.: TraitDescription>> - anArrayOfSelectorsOrTrait ^TraitExclusion with: self exclusions: anArrayOfSelectorsOrTrait Another thing is to have ' apply only once' option, means that if particular trait has already used in one of superclasses, then exclude it from composition.
Cheers, Alexandre
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel  http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
participants (5)
-
Adrian Lienhard -
Alexandre Bergel -
Andrew P. Black -
Igor Stasenko -
Stéphane Ducasse