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 ...

+ Reply to Thread
Page 1 of 2 1 2 LastLast
Results 1 to 10 of 11

Method binding - a "super super" effect?

  1. Default 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..


  2. Default 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..
    >


  3. Default 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


  4. Default 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..
    >


  5. Default 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.


  6. Default 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.


  7. Default 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


  8. Default 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


  9. Default "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.

  10. Default 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.


+ Reply to Thread
Page 1 of 2 1 2 LastLast

Similar Threads

  1. Replies: 34
    Last Post: 11-04-2007, 06:09 AM
  2. "Can't locate object method "PV" via package "B::SPECIAL""
    By Application Development in forum Perl
    Replies: 3
    Last Post: 10-20-2007, 12:02 PM
  3. less obvious "super"
    By Application Development in forum Python
    Replies: 5
    Last Post: 09-10-2007, 07:43 AM
  4. Re: help - error when trying to call super class method
    By Application Development in forum Python
    Replies: 0
    Last Post: 09-10-2007, 12:30 AM
  5. using super() to call two parent classes __init__() method
    By Application Development in forum Python
    Replies: 3
    Last Post: 08-18-2007, 12:19 AM