Method binding - a "super super" effect? - Smalltalk
This is a discussion on Method binding - a "super super" effect? - Smalltalk ; Consider this (simple enough) class heirarchy:
Class1->Class2->Class3.
In the above situation, Class2 overrode a method that was defined in
Class1. Class3 inherited this overrode method from Class2, but it was
inadequate -- what Class3 actually needed was the original Class1
...
-
Method binding - a "super super" effect?
Consider this (simple enough) class heirarchy:
Class1->Class2->Class3.
In the above situation, Class2 overrode a method that was defined in
Class1. Class3 inherited this overrode method from Class2, but it was
inadequate -- what Class3 actually needed was the original Class1
method which was just overrode in Class2. I found that I had to copy
the method from Class1 down into Class3, which to me is a
less-than-desirable solution.
What I needed was an "arbitrary super" that would allow me to "skip a
level" so to speak, by doing something on the order of a "super super,"
or even a "super:2." Thus instead of copying an entire method down to
Class3, I could have done something on the order of "self (super:2)
method: object". I was told that this was simply not possible, and
just to be happy with copying code down from Class1 to Class3.
I believe that what I want to do is possible, just not something easily
done in 5 minutes. Obviously the VM method binding engine binds
methods, and searches class heirarchies in doing so. It seems to me
that if I knew where to "poke around and look," I could possibly
implement some sort of arbitrary super. My intuition tells me that
this should not take an act of congress to do, but who knows --
depending on the implementation I could be opening up a serious can of
worms here (and probably am).
Anyway, are there any virtual machine/method binding gurus out there
that could sort of point me in a direction and give me some advice?
I'm using VisualWorks 7.3.1, so I'd like advice on this particular
product, but I assume this example would apply to any Smalltalk out
there, and any general advice would be useful as well.
Thanks..
-
Re: Method binding - a "super super" effect?
You could try something like this:
overriddenMethod
| method |
method := self class superclass superclass
compiledMethodAt: #overriddenMethod.
self performMethod: method arguments: #()
Personally, though, I wouldn't recommend it. A better approach is
something like this:
Class1 >> basicOverriddenMethod
^self overriddenMethod
Class3 >> overriddenMethod
^self basicOverriddenMethod
Having said that, I would actually prefer to flip this around so that
basicOverriddenMethod does the real work and overriddenMethod just calls it:
Class1 >> basicOverriddenMethod
"Do important stuff"
Class1 >> overriddenMethod
^self basicOverriddenMethod
Class3 >> overriddenMethod
^self basicOverriddenMethod
This allows Class2 to override the method and change the way it works
while Class3 can call the basic method to return to the original
functionality.
In the long run, though, I'd take a good hard look at my class hierarchy
to determine why the superclass method isn't appropriate and possibly
consider changing the hierarchy to make it work in a more natural fashion.
David Buck
Simberon Inc.
www.simberon.com
nowhereface@aol.com wrote:
> Consider this (simple enough) class heirarchy:
>
> Class1->Class2->Class3.
>
> In the above situation, Class2 overrode a method that was defined in
> Class1. Class3 inherited this overrode method from Class2, but it was
> inadequate -- what Class3 actually needed was the original Class1
> method which was just overrode in Class2. I found that I had to copy
> the method from Class1 down into Class3, which to me is a
> less-than-desirable solution.
>
> What I needed was an "arbitrary super" that would allow me to "skip a
> level" so to speak, by doing something on the order of a "super super,"
> or even a "super:2." Thus instead of copying an entire method down to
> Class3, I could have done something on the order of "self (super:2)
> method: object". I was told that this was simply not possible, and
> just to be happy with copying code down from Class1 to Class3.
>
> I believe that what I want to do is possible, just not something easily
> done in 5 minutes. Obviously the VM method binding engine binds
> methods, and searches class heirarchies in doing so. It seems to me
> that if I knew where to "poke around and look," I could possibly
> implement some sort of arbitrary super. My intuition tells me that
> this should not take an act of congress to do, but who knows --
> depending on the implementation I could be opening up a serious can of
> worms here (and probably am).
>
> Anyway, are there any virtual machine/method binding gurus out there
> that could sort of point me in a direction and give me some advice?
> I'm using VisualWorks 7.3.1, so I'd like advice on this particular
> product, but I assume this example would apply to any Smalltalk out
> there, and any general advice would be useful as well.
>
> Thanks..
>
-
Re: Method binding - a "super super" effect?
> In the long run, though, I'd take a good hard look at my class hierarchy
> to determine why the superclass method isn't appropriate and possibly
> consider changing the hierarchy to make it work in a more natural fashion.
Thanks - this is exactly what I was looking for.
As far as changing the class heirarchy - "no can do." See this
"problem with LinkedList in VisualWorks" thread for why I wanted to do
this in the first place:
http://groups.google.com/group/comp....a4b6b049ddeb95
-
Re: Method binding - a "super super" effect?
Others have already responded with some suggestions to which I won't
add, and instead I suggest in the words of Kent Beck and XP, that this
is a code smell http://c2.com/xp/CodeSmell.html
It is generally accepted that inheritance is one of the weakest aspects
of OO and certainly deep inheritance hierarchies should be avoided in
preference of composition or other OO patterns. I propose that any
solution that, by any means, encodes intimate knowledge of the class
hierarchy and corresponding method implementations, exacerbates this
issue and makes for extremely brittle code. For example, simply
introducing a new super class in between Class1 and Class2 will break
your Class3 code.
Perhaps this sort of problem may be better served by support for
multi-methods or mixins. Someone else might chime in and suggest a
cleaner approach to this problem.
regards Denis
nowhereface@aol.com wrote:
> Consider this (simple enough) class heirarchy:
>
> Class1->Class2->Class3.
>
> In the above situation, Class2 overrode a method that was defined in
> Class1. Class3 inherited this overrode method from Class2, but it was
> inadequate -- what Class3 actually needed was the original Class1
> method which was just overrode in Class2. I found that I had to copy
> the method from Class1 down into Class3, which to me is a
> less-than-desirable solution.
>
> What I needed was an "arbitrary super" that would allow me to "skip a
> level" so to speak, by doing something on the order of a "super super,"
> or even a "super:2." Thus instead of copying an entire method down to
> Class3, I could have done something on the order of "self (super:2)
> method: object". I was told that this was simply not possible, and
> just to be happy with copying code down from Class1 to Class3.
>
> I believe that what I want to do is possible, just not something easily
> done in 5 minutes. Obviously the VM method binding engine binds
> methods, and searches class heirarchies in doing so. It seems to me
> that if I knew where to "poke around and look," I could possibly
> implement some sort of arbitrary super. My intuition tells me that
> this should not take an act of congress to do, but who knows --
> depending on the implementation I could be opening up a serious can of
> worms here (and probably am).
>
> Anyway, are there any virtual machine/method binding gurus out there
> that could sort of point me in a direction and give me some advice?
> I'm using VisualWorks 7.3.1, so I'd like advice on this particular
> product, but I assume this example would apply to any Smalltalk out
> there, and any general advice would be useful as well.
>
> Thanks..
>
-
Re: Method binding - a "super super" effect?
nowhereface@aol.com wrote:
> > In the long run, though, I'd take a good hard look at my class hierarchy
> > to determine why the superclass method isn't appropriate and possibly
> > consider changing the hierarchy to make it work in a more natural fashion.
>
> Thanks - this is exactly what I was looking for.
>
> As far as changing the class heirarchy - "no can do." See this
> "problem with LinkedList in VisualWorks" thread for why I wanted to do
> this in the first place:
>
> http://groups.google.com/group/comp....a4b6b049ddeb95
But you *can* do, so why not do?
Basically, SequenceableCollection contains a method that wrongly
assumes that a SequenceableCollection is indexable fast, right? I'd
guess that it was put there to avoid duplicating it in
ArrayedCollection and OrderedCollection.
The Collections hierarchy is good, but it isn't perfect. It isn't even
entirely consistent between Smalltalks, AFAIK. There's no reason to
treat it with undue reverence.
-
Re: Method binding - a "super super" effect?
Mike Anderson wrote:
> > As far as changing the class heirarchy - "no can do."
>> ...
> But you *can* do, so why not do?
Whoops, I mispoke.
I agree with what you wrote above 100%. I suppose what I meant by "no
can do" was "don't want to do."
The other writer was assuming I was talking about a custom class
structure I had designed myself, not something that was included with
the system. I'm not sure I'd want to rearrange the entire class
structure of the "canned system," especially for such a small
"problem." Yes, "can do," but do I want to? For one thing, Cincom may
very well "fix" this themselves in an upcoming release. For another
thing, I might have to continuously redo the work in every subsequent
release of VisualWorks. Basically, it's at the level where a "bandaid"
solution is probably best at this point, or perhaps even simply "do
nothing." And as you point out, the Collections class is actually
pretty well-designed (just not perfect, but what is?).
You make good points. Take care.
-
Re: Method binding - a "super super" effect?
Hi,
nowhereface doesn't seem like your real name, so anonymous...
There are two ways to do this. One is by using a special perform: in vw
that is undocumented and unsupported. Use at your own risk 
Define this in Object:
perform: selector withArguments: anArray startingAbove: aBehavior
"Send the receiver the message indicated by the arguments, starting
the lookup in the superclass of aBehavior. The argument selector is
the selector of the message. The arguments of the message are the
elements of anArray. Invoke messageNotUnderstood: if the selector
is not understood by the receiver. Fail the primitive if aBehavior
is not the class of anObject or any of its superclasses, or if
anArray is not an Array with the same number of elements as the
number of arguments expected by the looked-up method."
<primitive: 515 errorCode: ec>
^self primitiveFailed
The other way would require you to define some syntax and modify the
compiler. The VW bytecode that implements super sends takes the class
in which to start the lookup as one of its arguments. So for example
super printOn: aStream
typically compiles to
1 <44> push self
2 <10> push local 0
3 <1C> push {TheClassInWhichThisMethodIsDefined}
4 <F2 21> super send printOn:
so the top of stack contains the class above which to begin the method
lookup.
As far as syntax goes, in the Borning Ingalls Smalltalk-80 multiple
inheritance scheme one could write directed sends as
self.ClassName foo
I'm not sure of the semantics anymore (its a long time ago) but it
probably didn't work the way you'd expect because the scheme relied
heavily on doesNotUnderstand: and method copying/selector-renaming.
But you could use this syntax and compile
self.ClassName foo
to
push self
push {Class named ClassName}
super send foo
The compiler could check that ClassName is a superclass. But a thorough
job would also put checks in the class builder because if ever the class
was moved out from under ClassName the VM could easily crash. The super
send bytecode doesn't check that the receiver inherits from the class
above which the lookup is to begin. This isn't a problem with super;
the class to start above is the class containing the method so ergo the
receiver must inherit. But with these directed sends that isn't
necessarily the case.
So buyer beware 
HTH
nowhereface@aol.com wrote:
> Consider this (simple enough) class heirarchy:
>
> Class1->Class2->Class3.
>
> In the above situation, Class2 overrode a method that was defined in
> Class1. Class3 inherited this overrode method from Class2, but it was
> inadequate -- what Class3 actually needed was the original Class1
> method which was just overrode in Class2. I found that I had to copy
> the method from Class1 down into Class3, which to me is a
> less-than-desirable solution.
>
> What I needed was an "arbitrary super" that would allow me to "skip a
> level" so to speak, by doing something on the order of a "super super,"
> or even a "super:2." Thus instead of copying an entire method down to
> Class3, I could have done something on the order of "self (super:2)
> method: object". I was told that this was simply not possible, and
> just to be happy with copying code down from Class1 to Class3.
>
> I believe that what I want to do is possible, just not something easily
> done in 5 minutes. Obviously the VM method binding engine binds
> methods, and searches class heirarchies in doing so. It seems to me
> that if I knew where to "poke around and look," I could possibly
> implement some sort of arbitrary super. My intuition tells me that
> this should not take an act of congress to do, but who knows --
> depending on the implementation I could be opening up a serious can of
> worms here (and probably am).
>
> Anyway, are there any virtual machine/method binding gurus out there
> that could sort of point me in a direction and give me some advice?
> I'm using VisualWorks 7.3.1, so I'd like advice on this particular
> product, but I assume this example would apply to any Smalltalk out
> there, and any general advice would be useful as well.
>
> Thanks..
>
--
_______________,,,^..^,,,____________________________
Eliot Miranda Smalltalk - Scene not herd
-
Re: Method binding - a "super super" effect?
> There are two ways to do this. One is by using a special perform: in vw
> that is undocumented and unsupported. Use at your own risk 
>
> [snip]
Eliot, great reply as usual. Thanks very much for the insights!
Paolo
-
"Super don't go high enough" Re: Method binding - a "super super"effect?
Denis Johnson wrote:
> ... It is generally accepted that inheritance is one of the weakest aspects
> of OO and certainly deep inheritance hierarchies should be avoided ... simply
> introducing a new super class in between Class1 and Class2 will break
> your Class3 code.
I agree. Super is way too tricky, because as you point out,
it makes us depend not only on other classes, but also on
the relationships those classes have between them.
I think it would be very difficult to try to express the
assumptions that using 'super' makes, with any any kind
of formal interface or assertion.
However, here's a possible 'pattern' to go around the problem
(might be called: "Super don't go high enough").
===============================================================
PATTERN: "Super don't go high enough"
CONTEXT:
Assume we have classes Class1->Class2->Class3.
Class2 inherits Class1, Class3 inherits Class2.
They each define their own versions of method #x,
Class1>>#x, Class2>>#x and Class3>>#x.
Assume we are using a language that provides the
'super' -construct.
PROBLEM:
In Class3>>#x you would like to use the method
Class1>>#x, in the context of the instance of
Class3.
FORCES:
You can not do this by calling 'super x', nor is the
fictional 'super super x' possible. But even if you
could, you would be creating more dependencies than
you like.
Calling 'super x' is more fragile than calling 'self x'.
Why? Because the number of classes where a redefinition
of #x can break the code of Class3 is bigger with 'super'
than it is with 'self'. Thus, 'self' is always better
than 'super' - from the point of view of writing robust,
maintainable, reusable code.
SOLUTION:
1. Rename the method Class1>>#x to Class1>>#y.
2. Create a new method Class1>>#x, with source-code:
x
^self y
3. In Class3, call 'self y', (instead of 'super super x').
CONSEQUENCES:
1. Class3 can now execute the same code as the original
Class1>>#x, in its own context, by calling 'self y'.
2. Existing code that calls #x still works, because it
does the same as the original #x used to do.
3. The construct 'super' is not needed at all, making
the code simpler, more understandable, more robust.
4. There is one more method-call to execute, and one more,
very simple, method.
===================================================================
-Panu Viljamaa
P.S.
About the notation: I use the format AClass >> #aMethod to
refer to a method defined in a specific class. '>>#' is
longer than '::' used in some other languages. But it has
the benefit that (in Smalltalk) I can define #>> for Class
to take a symbol argument, and to return the CompiledMethod
-instance of the method referred to.
-
Re: "Super don't go high enough" Re: Method binding - a "super super"effect?
I like your suggestion Panu. It is a simple approach using standard
language facilities and as you say, with this approach we avoid the
brittleness and the use of 'super' at all.
The only potential minor negative of this approach is possibly needing
to override the original Class1 >>x implementation from within your own
Smalltalk module (package or parcel in VW) if you do not own Class1,
however this is less likely. Even so, managing the override (if indeed
needed at all) is probably preferable then the brittleness of the
'super' based approach.
Thanks for the follow up, cheers Denis
p.s. I could not cross post this response to comp.software.patterns on
my news server so it has been removed.
panu@nospam.com wrote:
> Denis Johnson wrote:
>
>> ... It is generally accepted that inheritance is one of the weakest
>> aspects
>> of OO and certainly deep inheritance hierarchies should be avoided ...
>> simply
>> introducing a new super class in between Class1 and Class2 will break
>> your Class3 code.
>
>
> I agree. Super is way too tricky, because as you point out,
> it makes us depend not only on other classes, but also on
> the relationships those classes have between them.
>
> I think it would be very difficult to try to express the
> assumptions that using 'super' makes, with any any kind
> of formal interface or assertion.
>
> However, here's a possible 'pattern' to go around the problem
> (might be called: "Super don't go high enough").
>
>
> ===============================================================
> PATTERN: "Super don't go high enough"
>
> CONTEXT:
> Assume we have classes Class1->Class2->Class3.
> Class2 inherits Class1, Class3 inherits Class2.
> They each define their own versions of method #x,
> Class1>>#x, Class2>>#x and Class3>>#x.
>
> Assume we are using a language that provides the
> 'super' -construct.
>
>
> PROBLEM:
> In Class3>>#x you would like to use the method
> Class1>>#x, in the context of the instance of
> Class3.
>
> FORCES:
> You can not do this by calling 'super x', nor is the
> fictional 'super super x' possible. But even if you
> could, you would be creating more dependencies than
> you like.
>
> Calling 'super x' is more fragile than calling 'self x'.
> Why? Because the number of classes where a redefinition
> of #x can break the code of Class3 is bigger with 'super'
> than it is with 'self'. Thus, 'self' is always better
> than 'super' - from the point of view of writing robust,
> maintainable, reusable code.
>
>
> SOLUTION:
> 1. Rename the method Class1>>#x to Class1>>#y.
> 2. Create a new method Class1>>#x, with source-code:
> x
> ^self y
> 3. In Class3, call 'self y', (instead of 'super super x').
>
> CONSEQUENCES:
> 1. Class3 can now execute the same code as the original
> Class1>>#x, in its own context, by calling 'self y'.
> 2. Existing code that calls #x still works, because it
> does the same as the original #x used to do.
> 3. The construct 'super' is not needed at all, making
> the code simpler, more understandable, more robust.
> 4. There is one more method-call to execute, and one more,
> very simple, method.
>
> ===================================================================
>
> -Panu Viljamaa
>
> P.S.
> About the notation: I use the format AClass >> #aMethod to
> refer to a method defined in a specific class. '>>#' is
> longer than '::' used in some other languages. But it has
> the benefit that (in Smalltalk) I can define #>> for Class
> to take a symbol argument, and to return the CompiledMethod
> -instance of the method referred to.
Similar Threads
-
By Application Development in forum PHP
Replies: 34
Last Post: 11-04-2007, 06:09 AM
-
By Application Development in forum Perl
Replies: 3
Last Post: 10-20-2007, 12:02 PM
-
By Application Development in forum Python
Replies: 5
Last Post: 09-10-2007, 07:43 AM
-
By Application Development in forum Python
Replies: 0
Last Post: 09-10-2007, 12:30 AM
-
By Application Development in forum Python
Replies: 3
Last Post: 08-18-2007, 12:19 AM