Hi Adrian, I like the idea of your class factory. For years I have been using something very similar to create throwable classes. For example, in the package Spy (available on squeaksource) I have a class AbstractSpyTest and the following methods: AbstractSpyTest>>createClassNamed: AbstractSpyTest>>createClassNamed:superclass: then, within a test method, I can do: testMyExample | cls | cls := self createClassNamed: #C1. cls compile: 'giveMyFive ^ 5'. ... in the tearDown method I have: AbstractSpyTest>>tearDown super tearDown. classes ifNotNil: [:clss | clss do: #removeFromSystem ]. where 'classes' is an instance variable of AbstractSpyTest I used this piece of code for many years already, and I have always been happy so far. I also take care that the classes are created in a class category different from the one of my application. You propose:
class := ClassFactory newSubclass: Point with: [ :f | f metaSide compile: 'somePoint ^ self x: 2 y: 3'. f compile: '+ arg ^ self x + arg x ..... 3' ].
].
I find this difficult to remember. Do you manage automatic class removing in the tearDown? Cheers, Alexandre On 28 Dec 2009, at 23:07, Adrian Kuhn wrote:
`ClassFactoryForTestCase` is a awesome tool when you need to create throw-away classes for tests. And the new akuhn/SUnit includes a DSL that makes creating anonymous classes even simpler!
The new DSL is put in a new class to avoid compatibility issues. To create an anonymous class just do
class := ClassFactory newClass.
this creates a new subclass of Object. The creates classes is automatically reclaimed by garbage collection when no longer used. That is, tear down of class factory is not required anymore.
The class is created without logging and not registered with the system. That is, `Object subclasses` does not include the created class.
To create a subclass of a specific class do
class := ClassFactory newSubclass: Point.
To create a subclass with accessors do
class := ClassFactory newSubclass: Point with: [ :f | f compileAccessorsFor: 'color' ].
If you want getters or setters only, use `#compileSetterFor:` or `#compilerGetterFor:`. If you want an instance variable without accessor, use `#declareInstVar:`.
To create a subclass with methods do
class := ClassFactory newSubclass: Point with: [ :f | f compile: 'answer ^ 42' ].
NB: please note that class factory compiles silently without logging.
To create a method on the class side do
class := ClassFactory newSubclass: Point with: [ :f | f forClass: [ :cf | cf compile: 'somePoint ^ self x: 2 y: 3' ]].
In fact, the class side factory `cf` supports the same protocol as the instance side factory. Please note that creating instance variables on the class side creates "class instances variables" and not "instance class variables". That is, they are local to the creates class but not to subclasses of the created class. Typically this should not be a limitation since you only create one class without further subclasses.
Also, please note that the created classes and all instances created from that class are ment to be thrown away after their use. The created class is not registered with the system, and thus when you change the instance size of its superclass the created instances will not be updated.
Gofer it disablePackageCache; squeaksource: 'akuhn'; package: 'SUnit'; package: 'SUnitGUI'; load
--AA
_______________________________________________ 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 ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.