<div dir="ltr">Just in case anyone wonders: a workaround is to make the uses list empty #(), this will remove the traits from a class.<div><br></div><div>And if I would not use traits, I wouldn't have known that. I use them to give objects a common protocol based on a few would-be template methods that are "required" by the trait (as described in the paper). I don't like to impose abstract superclasses if there is no common, mandatory state, such as instance variables.</div><div><br></div><div>Often my trait methods are general defaults that implement the protocol simply, but not efficiently. This allows the user classes to adopt the protocol quickly, based on a few "primitives" (not real primitives, but the template methods). More efficient implementations can replace the trait methods later. But it gets you started.</div><div><br></div><div>For the same reason I provide traits if I want others to implement that protocol in their objects. At the same time, the traits "document" that protocol, like interfaces in statically typed languages. Abstract superclasses fulfill the same requirements, but seem to dictate inheritance. While you can also just copy their methods, the copies will be out of date when these methods are changed in the abstract superclass.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Am Do., 28. März 2019 um 16:22 Uhr schrieb <<a href="mailto:patrick.rein@hpi.uni-potsdam.de">patrick.rein@hpi.uni-potsdam.de</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">The test documents the (currently not working) workflow for removing a trait from a class by simply removing the "uses:" line from the class definition. To make this work, we would have to make the Class>>#subclass:instanceVariableNames:classVariableNames:poolDictionaries:category: method aware of traits. The method would have to reset the trait composition as Class>>#subclass:uses:instanceVariableNames:classVariableNames:poolDictionaries:category: currently does. Potentially, the change could also be embedded deeper in the class creation code to avoid that duplication and make the other class creation methods more robust. <br>
<br>
I am hesitant, as I am aware that traits have been prevented from being integrated more deeply so far. At the same time, the described missing workflow has already led users to struggle with using traits in the first place. So as they are part of the system I would rather improve their usability. Any other oppinions?<br>
<br>
Bests<br>
Patrick<br>
<br>
>Patrick Rein uploaded a new version of TraitsTests to project The Inbox:<br>
><a href="http://source.squeak.org/inbox/TraitsTests-pre.19.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/inbox/TraitsTests-pre.19.mcz</a><br>
><br>
>==================== Summary ====================<br>
><br>
>Name: TraitsTests-pre.19<br>
>Author: pre<br>
>Time: 28 March 2019, 3:30:48.769796 pm<br>
>UUID: 2ed07595-23e5-5f41-92ef-17c27ad0a017<br>
>Ancestors: TraitsTests-ul.18<br>
><br>
>Adds a test case for removing traits from a class by simply executing a class creation method without a trait composition. This does currently not yet work.<br>
><br>
>=============== Diff against TraitsTests-ul.18 ===============<br>
><br>
>Item was added:<br>
>+ ----- Method: TraitTest>>expectedFailures (in category 'failures') -----<br>
>+ expectedFailures<br>
>+ <br>
>+      ^ #(testRemoveTraitBySimpleClassDefinition)!<br>
><br>
>Item was added:<br>
>+ ----- Method: TraitTest>>testRemoveTraitBySimpleClassDefinition (in category 'testing') -----<br>
>+ testRemoveTraitBySimpleClassDefinition<br>
>+ <br>
>+      | classAv1 classAv2 |<br>
>+      classAv1 := self createClassNamed: #TraitTestMethodClassA superclass: Object uses: T1.<br>
>+      classAv2 := self createClassNamed: #TraitTestMethodClassA superclass: Object.<br>
>+ <br>
>+      self assert: classAv1 == classAv2.<br>
>+      self assert: classAv2 traits isEmpty.!<br>
><br>
>Item was added:<br>
>+ ----- Method: TraitsTestCase>>createClassNamed:superclass: (in category 'utility') -----<br>
>+ createClassNamed: aSymbol superclass: aClass<br>
>+      | class |<br>
>+      class := aClass<br>
>+              subclass: aSymbol<br>
>+              instanceVariableNames: ''<br>
>+              classVariableNames: ''<br>
>+              poolDictionaries: ''            <br>
>+              category: self categoryName.<br>
>+      self createdClassesAndTraits add: class.<br>
>+      ^class!<br>
><br>
><br>
<br>
</blockquote></div>