I'm learning a basics of Smalltalk. There's a super
keyword which is used to call a method from superclass inside a subclass method:
Object subclass: # A
test
^1
A subclass: # B
test
^2
callSuper
^super test
So B new callSuper
evaluates to 1
.
OK. That's clear.
So now, I'm defining a bunch of class methods for B
class:
createNew1
^super new
createNew2
^self new
create
^self
createSuper
^super
And they evaluates respectively to a B
, a B
, B
and an error (which shows me that super
is not a cast to subclass but kind of a message dispatcher).
Why am I getting instances of B
class despite super
keyword? And what's a difference between a B
and B
objects? I've started to think that the B
object is a special, singletone instance (just like static
attributes are implemented in other languages) of class B
, but still - I've checked and it's class is a B
and subclass is an A
.
What is the semantics of super
keyword in class methods? How it differs from semantics inside objects methods? What really is the object which can be obtained by calling self
inside class method?
I'm going to answer this by myself despite that all the other answers are technically correct. That's because I was knowing about metaclasses and it seems that I have a proper semantics of super
in my head, yet I was still getting unexpected results.
Turns out that I've misunderstood the basis of inheritance in Smalltalk and how methods are called.
I was thinking that for such code ...
Object subclass: #A
test
^'A'
getTest
^self test
A subclass: # B
test
^'B'
runTest
^super getTest
... the expression B new runTest
is evaluated to 'A'
- that means, the method from the superclass is evaluated in upcasted object.
But it isn't.
It's evaluated to 'B'
, because there's no upcasting and when we're calling any method inside a superclass method - the search starts in the real class of the object, not class from which evaluated method comes.
As a result, calling ^self new
and ^super new
, while not defining a new
in any of the classess, have the same effect - since both of them ends up with calling Behaviour's new
implementation in the context of self
.