[Q] Instance-Specific Behavior

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[Q] Instance-Specific Behavior

Blaine Buxton
Hello,
I was reading Kent Beck's "Guide to Better Smalltalk" recently and ran
across an article on instance-specific behavior. It seemed like a lot of
fun and something to oh and ah the java folks. Anyway, I typed the
following in a workspace:

| b md inst |
b:=Behavior new.
b instanceSpec: Object instanceSpec.
b methodDictionary: MethodDictionary new.
b superclass: Object.

b basicCompile: 'dodo ^''la la'''.
b inspect.

Now, if I select and "Evaluate It". I get an inspector on my new Behavior
object. There are no methods in his method dictionary at all! Is this
right? Anyway, I replaced Behavior with ClassDescription and re-did it.
This time, I get a message in my inspectors that #name is the subclasses
responsibility. OK, So I implemented a TempClassDescription with #name
implemented to return 'foo'. And re-ran with my TempClassDescription and
I still get no methods in my method dictionary! Alright, I change
TempClassDescription to Class and re-ran it. Still no methods, so I then
used Metaclass and my methods appeared (even though they showed their
class as nil) and creating a new instance worked and responded to: #dodo.
But, this seems a little much since Metaclass should be a soleInstance.

Anyway, how I should go about getting instance specific behavior in
Dolphin. I also tried this in Squeak and got some interesting results as
well.

The code above is pretty much taken from Kent's article, but made simpler
for my excursions...Anyway, I was just playing around with this
stuff....=) Seemed cool to me....

Thanks,
Blaine Buxton


Reply | Threaded
Open this post in threaded view
|

Re: [Q] Instance-Specific Behavior

Andy Bower
Blaine,

 From a message posted to this group in January, see below.

Please note that the #assumeInstanceBasedBehavior method has now been
included in the Dolphin 5 base system as Object>>allowPerInstanceBehavior
(so it won't need to be re-added).

Best Regards,

Andy Bower
Dolphin Support
http://www.object-arts.com
---
Are you trying too hard?
http://www.object-arts.com/Relax.htm
---

-----

Folks,

An interesting post came up in c.l.s recently with someone wanting to see if
instance based behaviour could be added to objects in Smalltalk (and in this
case Dolphin). Rather than cross post my reply (which might result in excess
pollution) I've just decide to post my reply separately here. Some of you
may find this amusing to play with.

"Artur Biesiadowski" <[hidden email]> wrote in message
news:[hidden email]...

> >> Is there any smalltalk-like system which allows you to redefine
> >> behaviour of single instance ? Instead of redefining method for class,
> >> do it only for single instance and only then maybe propagate it to
> >> entire system.
> >
> > You can do that in Smalltalk.  Or Lisp.
>
> So I can get Dolphin Smalltalk for example, create collection of 20
> instance of my class, select one of them, do something (what method
> should I call?) and normal method edition window will appear, but just
> modifying code for this single instance ? And if I'll clear contents of
> array, what will happen to code ? It will be deleted automagically or
> orphaned ? In latter case, how can I access it later ?

Yes, and this is how you do it. The following code is for Dolphin. Most
Smalltalks will be able to do something similar but the implementation will
typically be via private methods and so won't be consistent between
dialects. If you haven't got a copy of Dolphin yet then try this with the 30
day Dolphin Professional trial version available at:

http://www.object-arts.com/Trial

Fire up the IDE and open a workspace. Copy the following into the workspace,
select it, and then choose Workspace/File it in.

+++ snip after this line +++

!Object methodsFor!
assumeInstanceBasedBehavior
    "Private - Make the receiver a prototypical instance of it's own private
class. From this point on
    the instance may have it's own behaviour modified or added to."

    | metaSuperclass newMetaclass newClass |

    "Create a private new metaclass"
    metaSuperclass := self class class.
    (newMetaclass := Metaclass new)
        methodDictionary: MethodDictionary new;
        instanceSpec: metaSuperclass instanceSpec;
        superclass: metaSuperclass.

    "Create a private instance of this metaclass as the new class"
    (newClass := newMetaclass new)
        methodDictionary: MethodDictionary new;
        instanceSpec: self class instanceSpec;
        setName: ('_', self class name) asSymbol;
        superclass: self class.

    self becomeA: newClass.! !

    !Object categoriesFor: #assumeInstanceBasedBehavior!private! !

+++ snip before this line +++

I'm not sure the formatting will make it through NNTP but it should work
anyway. This is a new method added to Object (and in this case I think it
*is* appropriate to extend Object - just harking back to another thread).
The method creates a new private (hidden) class and metaclass pair for any
object that has #assumeInstanceBasedBehavior called on it. This pair hold
their own private method dictionaries so prototypical methods can be added.
Note you can add both instance and class based prototypical methods.

The new classes will not be visible in the standard browsers but could be
made so if necessary. They will also disappear and be garbage collected when
the prototypical object has no remaining  references.

Let' test this out. Copy the following into a Dolphin workspace and execute
each line individually (place the cursor on the line and press Ctrl+E).
Stuff in "" is comment. When you see a line with "Ctrl+D" then press this
and it will evaluate the line and display a result. We'll work on Dates for
a simple but rather boring demo.

a := Date today. "Ctrl+D"
b := Date today.
c := Date today.

Three dates. Add them to an array (your suggestion)

array := Array with: a with: b with: c. "Ctrl+D"

Let's make the first two have prototypical behaviour.

a assumeInstanceBasedBehavior.
b assumeInstanceBasedBehavior.

Ask for the weekdays of the days in the array.

array collect: [:each | each weekday ]. "Ctrl+D"

No surprise there. Even thought the first two have the capability of
prototypical behaviour they are inheriting from their original class (Date).
Now let's add that "Friday feeling" to the first date only. We'll change the
behaviour of the #weekdayIndex method to always answer 5. Then see what
happens when we ask for the #weekday again (which makes use of
#weekdayIndex). Note we use the standard compiler to compile in the new
method into a's class.

a compile: 'weekdayIndex ^5'.

Now ask for the days again:

array collect: [:each | each weekday ]. "Ctrl+D"

Assuming that it's not actually Friday when you try this you should see a
difference. Notice that only the first date has got the new behaviour. The
second prototypical date is still inheriting directly from Date. Try
modifying it's code for a Saturday.

a compile: 'weekdayIndex ^6'.
array collect: [:each | each weekday ]. "Ctrl+D"

Now lets see how we can tell these are different from normal Dates

array collect: [:each | each class ]. "Ctrl+D"

Try looking for _Date in the Class Hierarchy Browser; it should be nowhere
to be found. You can find the hidden classes by a roundabout route:

(Metaclass allInstances collect: [:each | each instanceClass]) select:
[:each | each superclass == Date] "Ctrl+D"

Now free up our variables and look again:

a := b := c := array := nil.
(Metaclass allInstances collect: [:each | each instanceClass]) select:
[:each | each superclass == Date] "Ctrl+D"

You should find that the _Date classes have disappeared automagically.

I notice from your original post that you wanted to be able to view the
instance based methods in a browser. This would be fairly easy to arrange
but is beyond the scope of this excercise. Still, I hope you've found the
above to be amusing and food for thought.

Best Regards,

Andy Bower
Object Arts Ltd.
http://www.object-arts.com
---
Are you trying too hard?
http://www.object-arts.com/Relax.htm
---


Reply | Threaded
Open this post in threaded view
|

Re: [Q] Instance-Specific Behavior

Udo Schneider
In reply to this post by Blaine Buxton
> "Blaine Buxton" <[hidden email]> schrieb im Newsbeitrag
news:[hidden email]...
> Hello,
> I was reading Kent Beck's "Guide to Better Smalltalk" recently and ran
> across an article on instance-specific behavior. It seemed like a lot of
> fun and something to oh and ah the java folks. Anyway, I typed the
> following in a workspace:

Andy posted an example for instance specific behaviour here some time ago. I
built a package with Andys Code but with an interface similar to the one
mentioned in Kent Beck's Book.

If your news server strips binary attachments you can download it at
http://www.homeaddress.de/US_Specialized_Instances.zip


Udo








begin 666 US Specialized Instances.pac
M?"!P86-K86=E('P-"G!A8VMA9V4@.CT@4&%C:V%G92!N86UE.B G55,@4W!E
M8VEA;&EZ960@26YS=&%N8V5S)RX-"G!A8VMA9V4@<&%X5F5R<VEO;CH@,#L-
M"@EB87-I8T-O;6UE;G0Z("<G+@T*#0IP86-K86=E(&)A<VEC4&%C:V%G959E
M<G-I;VXZ("<P+C P-"<N#0H-"B)!9&0@=&AE('!A8VMA9V4@<V-R:7!T<R(-
M"@T*(D%D9"!T:&4@8VQA<W,@;F%M97,L(&QO;W-E(&UE=&AO9"!N86UE<RP@
M9VQO8F%L(&YA;65S+"!R97-O=7)C92!N86UE<R(-"G!A8VMA9V4@8VQA<W-.
M86UE<PT*"7EO=7)S96QF+@T*#0IP86-K86=E(&UE=&AO9$YA;65S#0H)861D
M.B C3V)J96-T("T^("-I<U-P96-I86QI>F5D.PT*"6%D9#H@(T]B:F5C=" M
M/B C<W!E8VEA;&EZ93L-"@EA9&0Z("-/8FIE8W0@+3X@(W-P96-I86QI>F4Z
M.PT*"7EO=7)S96QF+@T*#0IP86-K86=E(&=L;V)A;$YA;65S#0H)>6]U<G-E
M;&8N#0H-"G!A8VMA9V4@<F5S;W5R8V5.86UE<PT*"7EO=7)S96QF+@T*#0HB
M0FEN87)Y($=L;V)A;"!.86UE<R(-"G!A8VMA9V4@8FEN87)Y1VQO8F%L3F%M
M97,Z("A3970@;F5W#0H)>6]U<G-E;&8I+@T*(E)E<V]U<F-E($YA;65S(@T*
M<&%C:V%G92!A;&Q297-O=7)C94YA;65S.B H4V5T(&YE=PT*"7EO=7)S96QF
M*2X-"@T*(D%D9"!T:&4@<')E<F5Q=6ES:71E(&YA;65S(@T*<&%C:V%G92!S
M9710<F5R97%U:7-I=&5S.B H261E;G1I='E3970@;F5W#0H)861D.B G1&]L
M<&AI;B<[#0H)>6]U<G-E;&8I+@T*#0IP86-K86=E(0T*#0HB0VQA<W,@1&5F
M:6YI=&EO;G,B(0T*#0HB3&]O<V4@365T:&]D<R(A#0H-"B%/8FIE8W0@;65T
M:&]D<T9O<B$-"@T*:7-3<&5C:6%L:7IE9 T*"5YS96QF(&-L87-S(&YA;64@
M8F5G:6YS5VET:#H@)U\G(0T*#0IS<&5C:6%L:7IE#0H)(E!R:79A=&4@+2!-
M86ME('1H92!R96-E:79E<B!A('!R;W1O='EP:6-A;"!I;G-T86YC92!O9B!I
M="=S(&]W;B!P<FEV871E#0H)8VQA<W,N($9R;VT@=&AI<R!P;VEN="!O;B!T
M:&4@:6YS=&%N8V4@;6%Y(&AA=F4@:70G<R!O=VX@8F5H879I;W5R(&UO9&EF
M:65D(&]R(&%D9&5D('1O+B(-"@T*"7P@;65T85-U<&5R8VQA<W,@;F5W365T
M86-L87-S(&YE=T-L87-S('P-"@T*"2)#<F5A=&4@82!P<FEV871E(&YE=R!M
M971A8VQA<W,B#0H);65T85-U<&5R8VQA<W,@.CT@<V5L9B!C;&%S<R!C;&%S
M<RX-"@DH;F5W365T86-L87-S(#H]($UE=&%C;&%S<R!N97<I#0H)"6UE=&AO
M9$1I8W1I;VYA<GDZ($UE=&AO9$1I8W1I;VYA<GD@;F5W.PT*"0EI;G-T86YC
M95-P96,Z(&UE=&%3=7!E<F-L87-S(&EN<W1A;F-E4W!E8SL-"@D)<W5P97)C
M;&%S<SH@;65T85-U<&5R8VQA<W,N#0H-"@DB0W)E871E(&$@<')I=F%T92!I
M;G-T86YC92!O9B!T:&ES(&UE=&%C;&%S<R!A<R!T:&4@;F5W(&-L87-S(@T*
M"2AN97=#;&%S<R Z/2!N97=-971A8VQA<W,@;F5W*0T*"0EM971H;V1$:6-T
M:6]N87)Y.B!-971H;V1$:6-T:6]N87)Y(&YE=SL-"@D):6YS=&%N8V53<&5C
M.B!S96QF(&-L87-S(&EN<W1A;F-E4W!E8SL-"@D)<V5T3F%M93H@*"=?)RP@
M<V5L9B!C;&%S<R!N86UE*2!A<U-Y;6)O;#L-"@D)<W5P97)C;&%S<SH@<V5L
M9B!C;&%S<RX-"@T*"7-E;&8@8F5C;VUE03H@;F5W0VQA<W,N(0T*#0IS<&5C
M:6%L:7IE.B!A4W1R:6YG#0H)<V5L9B!S<&5C:6%L:7IE+@T*"7-E;&8@8VQA
M<W,@8V]M<&EL93H@85-T<FEN9PT*(2 A#0HA3V)J96-T(&-A=&5G;W)I97-&
M;W(Z("-I<U-P96-I86QI>F5D(7!R:79A=&4A<W!E8VEA;&EZ:6YG(2 A#0HA
M3V)J96-T(&-A=&5G;W)I97-&;W(Z("-S<&5C:6%L:7IE(7!R:79A=&4A<W!E
M8VEA;&EZ:6YG(2 A#0HA3V)J96-T(&-A=&5G;W)I97-&;W(Z("-S<&5C:6%L
M:7IE.B%P<FEV871E(7-P96-I86QI>FEN9R$@(0T*#0HB16YD(&]F('!A8VMA
M9V4@9&5F:6YI=&EO;B(A#0H-"B -"B)":6YA<GD@1VQO8F%L<R(A#0H-"B)2
.97-O=7)C97,B(0T*#0H`
`
end


Reply | Threaded
Open this post in threaded view
|

Re: [Q] Instance-Specific Behavior

Andy Bower
In reply to this post by Andy Bower
Blaine,

Sorry, I just realized (thanks to your e-mail) that the
Object>>allowPerInstanceBehavior method is not shipped in the standard D5
product. I've uploaded the package to our website:

http://www.object-arts.com/Lib/Downloads/5.0/Per%20Instance%20Behavior.zip

Stick this in %

Best Regards,

Andy Bower
Dolphin Support
http://www.object-arts.com
---
Are you trying too hard?
http://www.object-arts.com/Relax.htm
---