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
> [email protected]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project