Search code examples
inheritancesmalltalksuperclasssuperself

Why does the result of `Subclass new superclass` differ from `Subclass superclass`?


Consider the following code:

Object subclass: Two []
Two subclass: Three [
    superclass [^super class]
]
Three subclass: Five []    

Why does Five new superclass return Five while Five superclass returns Three?

From what I read in the source code of the Object class in both Dolphin Smalltalk and GNU Smalltalk, the class uses self which is why Five new superclass returns Five. I do not understand why Five superclass returns Three, however.


I'm using an online version of the GNU Smalltalk interpreter.


Solution

  • Let's depict the hierarchy

    Object
      Two
        Three
          Five
    

    Also, we have the (instance side) method

    Three >> superclass
      ^super class
    

    First of all, let's recall that Five superclass is Three just because Five is a direct subclass of Three (nothing special here).

    Now let's see why Five new superclass answers with Five instead. For this we need to closely analyze the superclass method above.

    Since the message #class is implemented at the top of the hierarchy (every object knows how to answer its class), the method at Three just refers to the inherited class method implemented in Object. Hence, Three >> superclass is essentially equivalent to class (it does nothing but invoking the inherited method class which it already got "for free"). Finally, since Five inherits from Three, when we send superclass to any of its instances (Five new superclass), we get the same we would have gotten for any instance of Three (inheritance again), which is the class of the instance which receives the message, Five in this case.

    What might be confusing here is the use of super in Three >> superclass. But in this case super is entirely equivalent to self. It wouldn't have been, had Three implemented class in a way different from the one inherited from Object (which it didn't). So in fact, the method is equivalent to

    Three >> superclass
      ^self class
    

    meaning that for instances and subinstances of Three asking their superclass is the same as asking for their class.

    Another piece of confusion comes from the tricky selector chosen: superclass. By default, superclass is a message understood by classes, not instances. However, the trick here is to implement the same selector on the instance side of the class to bring confusion on purpose (and test your orientation). This is confusing because when we see superclass our brains "automatically" connect with the class that is above me. But that is only true if you are speaking to the class, not to any of its instances.

    To further uncover the trick, let's rename the selector to something less special

    Three >> foo
      ^super class
    

    and then try Five new foo, which will answer Five just because Five new is an instance of Five.