"Singletons" package on SM
Avi Bryant
avi at beta4.com
Thu Dec 4 10:36:59 UTC 2003
On Dec 4, 2003, at 12:17 AM, ducasse wrote:
Stef, thanks for taking the time to respond. It's late, so hopefully
my ramblings below make sense:
>> This package adds the #becomeSingleton method to Object, which will
>> transform the receiver into an instance of a new, anonymous subclass
>> of its original class.
>
> why subclass of the original class. because now if you do
> inst class superclass you will get your normal class. This is quite
> strange.
Why is that strange? I don't see anything wrong with that - it's the
exact semantics I wanted.
> You should have a look at my comparison
> http://www.iam.unibe.ch/~scg/Archive/Papers/
> Duca99aMsgPassingControl.pdf
>
> If I remember well in VW I did something similar, but
> I created a new behavior copied the format of the class to this
> behavior, then compile class to be superclass
> and superclass to be class superclass.
Ah, I may now understand your objection better - what you were doing in
your paper was trying to affect an entire class of objects at once,
transparently. I'm trying to affect a single instance, and it
doesn't need/want to be transparent. I'm not using the existing lookup
mechanism to hack in new semantics (like my Mixin implementation does,
for example), I'm really just trying to introduce a new way of defining
subclasses (that happen to have exactly one instance).
> Anyway have a look this was fun.
>
> What I would say is that these kinds of hack are fun but after to make
> them working in an integrated way
> you have much more problems.
Again, for my goal (anonymous, instance-based subclasses), I don't
think any further integration is really needed (well, it might be nice
to show the singleton methods in the Inspector, but that's really
minor). It's not a hack in that sense - I would have no qualms using
this in production code (I think - maybe someone can convince me
otherwise). I think the main integration problems would come if you
were introducing new CompiledMethods with source code into these
subclasses, but since I'm using MessageSends and blocks (through
Andreas' ObjectsAsMethods stuff, but could also be MethodWrappers),
there are no ugly calls to #compile: or anything.
>> My expectation is that this might be useful as a replacement for
>> specifying pluggable behavior with block inst vars or target/selector
>> pairs, particularly for UI classes.
>
> Why is it really a problem?
Two things. One is the idea of "unplanned reuse", which I think
Smalltalk generally excels at: if you have well factored code, it's
often very easy for someone to come along later and introduce a
subclass where you had no idea that someone would want to change the
behavior you started with, simply by redefining a few key methods.
However, this kind of reuse is only possible through subclassing - to
reuse code through composition, the developer has to have left you
explicit "pluggable" hooks. Since I think composition is often a
better solution than subclassing in other ways, I think this is a
shame. This puts subclassing and composition on equal grounds in that
respect.
Second, it's very common for someone to build in extensibility in two
ways (subclassing and composition) by having an abstract class that
defines a #subclassResponsibility, have some concrete classes that
fulfill this responsibility, and then have a Pluggable subclass that
allows the user to supply a block to fulfill the responsibility
instead. An example close to this is Set, IdentitySet, and
PluggableSet. With this delegation code, someone just has to mark the
extensibility points once with #subclassResponsibility, and that same
responsibility can either be fulfilled by an explicit subclass, or by
an anonymous instance-based subclass (ie, through composition), with no
need for the boilerplate of a "Pluggable" version. And note that, like
Traits, this approach may remove the need for copied code in
IdentitySet and IdentityDictionary - instead, you would have a separate
IdentityScanner class that implemented the revised #scanFor:, and to
make a Set *or* Dictionary into an Identity[Set|Dictionary], you could
say
collection delegate: #scanFor: to: (IdentityScanner for: collection).
Or something along those lines. Hmm... to achieve this otherwise you
would need the hierarchy
Set
PluggableSet
Dictionary
which is ugly for all kinds of reasons (including performance ones).
So even if you *are* planning for this kind of reuse, the block
pluggability still looks like it's worse. (Ok, having realized that, I
ought to rewrite this argument to be based entirely around that
example, but it really is late so I'll let the rambling stand).
Cheers,
Avi
More information about the Squeak-dev
mailing list
|