Hello. Today we are going to examine a very interesting subtlety
that you can apply in your programs.
To start with, we'll quickly review the dice program.
If you recall, in this exercise we defined the dice class in order
to define instances of this class and represent various dice faces.
We defined a class called DiceHandle.
Then we implemented the "plus" method
on the DiceHandle class,
to add DiceHandles and construct a new DiceHandle.
This is the code for this class.
We have DiceHandle new.
We create a new DiceHandle,
to which we add the dice of the receiver class
and the setting,
and we return this handle at the end of the method. Okay?
In this sequence we will see the difference,
in this "+" method, between writing DiceHandle new
and self class new.
And we'll see why one technique is better.
Here is the problem.
If I create a DiceHandle subclass called MemoDiceHandle,
and I want to add MemoDiceHandles,
with the "+" method, which is inherited from DiceHandle,
the result is an instance of the DiceHandle class.
Not of the MemoDiceHandle class.
This is a problem because when we add elements,
we want to get the same type of element back.
How do we do this?
Solution No. 1.
I change the implementation
of the "+" method on the DiceHandle class.
The "+" method, okay?
And I simply add this method: self handleClass.
Instead of defining the instance variable I wish to obtain,
I use a method that I call handleClass.
In DiceHandle, the DiceHandle class is returned,
and in the MemoDiceHandle subclass, MemoDiceHandle is returned.
So by simply redefining the handleClass method,
we obtain the correct instance when we add elements.
If we execute the same code,
using MemoDiceHandle instead, we get an instance of MemoDiceHandle,
because I redefined the handleClass method
in the MemoDiceHandle class. We got an instance of the subclass.
So we attained our objective.
The problem is that
each time we add a subclass to DiceHandle,
we must redefine the handleClass method.
If you don't, the "+" method will never return the correct class instance.
This is tedious. You must constantly redefine the method.
There are better ways.
Here's Solution No. 2.
Using the "+" method in DiceHandle, this time we will write:
self class new.
I'll ask the current receiver for its class,
in order to get an instance.
In fact, self class always returns the class of the receiver.
If it's the instance of a subclass,
it will return the correct class. For example, MemoDiceHandle.
We get instances of the same kind as that of the receiver.
As a conclusion,
as you saw,
when you send the message "+" to a DiceHandle,
if you set the name of the class you want an instance for,
in a sense you prevent yourself from creating subclasses.
But with self class new, "+" returns an instance of the receiver.
Of the potential subclass.
So it's much better to use self class new,
to directly get
an instance of the class according to the type of receiver.