Hello, this is a very advanced course.
We'll focus on how Pharo organizes classes
and instance relationships between classes.
It's really aimed at enthusiasts.
It's not essential to master, since you already use Pharo without it.
You can use Pharo for programming without knowing how it works.
But you may be unsatisfied if the course didn't explain how it functions.
Like explaining where "new" is defined,
or what the class of a metaclass is.
This video will explain all this stuff.
It doesn't matter if you don't understand straightaway.
But if it really interests you,
you can watch it several times.
There is one fundamental key here.
It's a fun aspect, which this transparency should explain.
The basic idea,
which we keep reiterating in this MOOC,
is that, as you should know, when we send a message to an object,
we search in the object's class via the instantiation link.
If it isn't there, we follow the inheritance chain.
We always start in the class, then follow the inheritance chain.
This rule must be followed systematically.
To explain metaclasses,
we summarize them in seven points, which are relatively simple.
Every object is an instance of a class.
That's difficult! Look at this example.
The object OrderedCollection is an instance of this class.
So far, it's clear.
The second point is that every class inherits from the Object class.
As we see here,
OrderedCollection and upwards inherit ultimately from Object.
Just a note for French speakers,
"eventually" means "ultimately."
It's confusing.
So,
we have our inheritance graph that inevitably leads to Object.
What is the responsibility of Object? It represents object behavior
common to all objects, such as error handling,
inserting a halt, and announcements.
Object is the root of the inheritance tree.
Its key responsibility is minimum behavior.
Returning to our list, every class is an instance of a metaclass.
We explained this in an earlier course.
A class X is the sole instance of the metaclass named X class.
We see that the OrderedCollection class
is an instance of the class OrderedCollection class.
It works the same way for the SequenceableCollection class,
and the Object class with the class Object class.
All classes are instances of another metaclass,
which takes the same name followed by "class."
Metaclasses are created
automatically when we create a class.
We send a "new" message to the metaclass to create the class.
Next point.
Metaclass hierarchy parallels class hierarchy.
Earlier, we explained that
OrderedCollection is an instance of its class,
and likewise for SequenceableCollection.
Now we need to specify the relationship between the two.
Since there's an inheritance relationship here, there's also one here.
In all cases.
That's why we say they are two parallel hierarchies.
When do we use this hierarchy?
If I send the "new" message to OrderedCollection,
where do I search? In the class.
I query in each class whether or not "new" has been defined.
Moving upwards, has it defined "new"? Yes or no.
Here we utilize the key I mentioned at the beginning.
To send a message, start with the class then follow the inheritance chain.
Up to this point,
it may seem clear, but now other questions come up.
What is Object class an instance of?
You might wonder.
And what is the superclass of Object class?
Does it work if we send a message to a metaclass?
Or if we send a message to whatever it is here?
Let's have a look.
The system says that every metaclass inherits from Class,
right up to Behavior.
Let's look at that, and answer the first question.
Object class is a class, hence it inherits from Class.
Class inherits from ClassDescription and Behavior.
Unlike in Pharo, in other systems such as Lisp
these two elements are a single class.
Pharo divides them for reuse.
Metaclass can be attached to ClassDescription
to utilize ClassDescription in two cases.
We see that Behavior, which represents the essence of a class,
inherits from Object.
So, if I send a message here,
it will travel all the way up to here.
It follows the inheritance tree from the Class level.
Now we want to know where "new" is defined.
The method for creating instances is defined in Behavior.
When I send the "new" message to OrderedCollection, what happens?
First, I search in the class.
Suppose that "new" is not redefined in the inheritance,
so I search all of the superclasses
until we find "new."
In a lookup, we search for a method and execute it on the receiver.
So, I find the "new" method and execute it on the receiver,
the class OrderedCollection, which creates a new instance
that we'll name 3 4, for example.
Okay?
We're using the key I spoke about.
We search the inheritance chain, starting with the receiver's class.
In a nutshell, what does Behavior represent?
It's the essence of an object that can have instances.
Objects with instances
must include a superclass link,
method dictionary, and description of instances (format).
The methods shown here include examples such as new, basicNew and new:.
The difference between new and basicNew
is that you must never redefine basicNew.
As we explained in the course on methods,
if you redefine a method starting with "basic," the method is inaccessible.
The original method.
There are other ways to access the compiled methods, as shown here.
Behavior is the essence of a class.
What is ClassDescription?
It's an abstract superclass shared by Class and Metaclass.
It adds facilities to Behavior,
such as naming instance variables, since class execution can be automatic.
ClassDescription adds such things.
Category organization concerns methods in your browser showing the protocols.
For example, a method can be stored in the printing protocol.
Also, the notion of a name.
Plus the maintenance of Change sets and the saving of changes in files.
You can look at that yourself.
This categorization exists because use is shared by Class and Metaclass.
The responsibility of Class
is to represent the classes we employ in Pharo.
This includes representation for classVariable names
and a better way of naming and compiling elements.
Once again, refer to the code.
Classes are instances of metaclasses.
If Object is an instance of a class named Object class,
and likewise for OrderedCollection,
the same applies to Class, ClassDescription, and Behavior.
So, Class is an instance of Class class
and ClassDescription is an instance of ClassDescription class.
The same applies to Behavior.
We must also look at the inheritance chain.
If there's an inheritance relationship between these two elements,
the same relationship exists here on the right.
As you see here, we can trace the inheritance chain.
Behavior class therefore inherits from Object class.
Now for the second last point.
Since every class is an instance of a metaclass, a question arises.
What is OrderedCollection class an instance of?
Since everything is an object in Pharo.
OrderedCollection class is therefore an instance of Metaclass.
Object class and Class class are instances of Metaclass.
All the metaclasses in the system are instances of Metaclass.
Furthermore, Metaclass inherits from ClassDescription.
It's an unusual class because it only has one instance.
And you can't name it because its name is defined by its instance.
That may seem barbaric.
So, we see that OrderedCollection
is an instance of OrderedCollection class, which takes its name.
All metaclasses are instances of Metaclass.
In the code, the main responsibility of Metaclass
is to create and initialize a single instance of itself.
There's only one question left to answer.
What is Metaclass an instance of?
Because Metaclass is a class, like OrderedCollection,
it is an instance of the class Metaclass class.
You'll see that Metaclass inherits from ClassDescription,
therefore Metaclass class inherits from ClassDescription class.
OrderedCollection class inherits from Object class
as OrderedCollection inherits from Object.
So, Metaclass is an instance of Metaclass class.
OrderedCollection is an instance of OrderedCollection class.
And Metaclass class is an instance of Metaclass,
just as Class class and Object class are instances of Metaclass.
This loop may seem bizarre, but it makes sense in context.
You don't need this to use Pharo, so feel free to overlook it.
But as this graph shows,
the key we spoke about earlier works perfectly.
Every time we send a message to an object, we look at its class
and its inheritance tree, as shown in these examples.
If I send a message to this instance, it leads me to Object.
If I send a message to the class,
I go to the metaclass and follow the inheritance.
If I send a message to a metaclass, where should I look?
In Metaclass, since the metaclass is an instance of Metaclass.
I follow the instantiation link to the end.
This is when a message is not understood or a method is only defined in Object.
Now, what if I send a message to Metaclass itself?
Where do I search?
First in Metaclass class, then I follow the inheritance chain.
So... oops!
It gets more complicated here.
Similarly, if I send a message to Metaclass class,
or to OrderedCollection class,
I look in the instance
of Metaclass class, which is Metaclass.
Like for OrderedCollection class, I follow this path.
You will see that this graph is entirely logical.
We cannot have an inconsistent graph
since the virtual machine only does one thing.
It looks for messages in the class and follows the inheritance chain.
This comprehensive graph is consistent with that process.
I find this exciting because I wondered about it myself.
So, to sum up, classes are objects and can receive messages.
The procedure is the same for all objects,
even if there are metaclasses with a sole instance,
which are not explicitly named.
But it's not essential to know that.