0:04
In the previous episodes, we have seen that the attributes
defined within the class represent informations
specific to each instance of the class.
Let us go back to our little example of the rectangle.
Each instance of rectangle, each Rectangle-type object
will have its own width, its own height.
Those are specific informations characterizing each rectangle.
Now, what does happen if several instances of a same class
need to access a same information,
a common information?
This is the object of today's episode.
In order to illustrate the problem we are interested in,
let us go back to our example of counting instances.
We have already had the chance to study it in the episodes
regarding the construction/destruction of an object.
Our goal is to account for all the instances existing
at a given time in a program.
For that, we need to have a memory area
0:51
accessible by every instance.
It will be incremented whenever an instance is created
and decremented every time an instance is destroyed.
When we had discussed this problem for the first time,
the only way we had to define this memory area,
acessible by every instance
in order to be incremented and decremented was to use a global variable.
Formerly, we were not plainly satisfied
with this declaration of a global variable.
Indeed, using global variables tends to be nefarious
in a program; it is a very poor solution.
A global variable, such as this one,
is not attached to any entity in the program.
Therefore, violates the principle of encapsulation
and is a sign of a poor modularization.
Moreover, this can induce harmful side effects.
Indeed, such a variable can be accessed
pretty much everywhere in the program, without any control.
Therefore, we should avoid this at all cost.
Alternatively, defining the counter as an attribute of the rectangle class
is clearly not a good solution either
since it would mean that each instance of rectangle
has its own counter. This is clearly not what we wish.
We wish to have a common area accessible by every instance.
Therefore, this solution is not good either.
The solution to this problem is to define the information we wish to be
common to all instances of the class
as a class attribute.
Unlike the attributes relative to instances
(the ones we were used to define up until now)
a class attribute is an attribute defined
inside the class, but matched with the reserved keyword "static".
Typically, let us us imagine a
program where severall Rectangle instances coexist.
To make things easier, there will be two.
5:50
Resorting to a class variable in order to account
for all the instances of a class
is naturally a relatively atypical example.
Of course, there are many other situations
where it is useful to share informations between several instances.
However, most of the time, it will be a constant.
Let us take an example.
This time, we will move away from our rectangle example
and imagine a situation where we need to
reperesent the employees of a company.
This is more of an administrative example.
Let us say that an employee is characterized by an age,
the in-service date.
7:28
This information is thus uselessly repeated for each employee.
There is thus code duplication;
this could induce maintenance troubles.
For example, let us imagine that, through a change of law,
the pensionable age is changed to 67 years.
We would thus need to dive into each instance
and modify this value everywhere.
Obviously, this may beget severe maintenance problems.
The solution is obviously to define this information
as a class variable
thanks to the reserved "keyword" static.
Typically, here, "age_retraite" (TN: means "pensionable_age")
would be a memory area
commonly accessible by all the instances.
However, it will not be duplicated in each of the instances.
Typically, this will disapear.
The same goes for each instance.
8:15
To sum up, we have seen, through the previous examples
that the class attributes are typically very practical
and useful when different objects (such as our employees)
need to access a common information (such as the official pensionable age).
We have seen it lets us avoid information duplication
and permits for a better maintenance of this information.
Also, please remember the case we had studied before,
regarding instance counting.
Here, the class variable was defined as a non-constance
since we need to
decrement/increment this value every time an object is created is destroyed.
Why, this situation is rather atypical.
Practically, most of the class variables
you will encounter will be used to represent constants useful for
all the instances of a given class.
Now, you know what a class attribute is,
a "static" attribute.
Is it possible to do the same thing with methods?
The answer is yes, and we will present it for the sake of completeness,
even though "static" methods are not used very frequently.
Also, it is not recommanded to use them in object-oriented programming.
A "static" method is simply
a method defined inside a class.
This declaration is preceded with the reserved keyword "static".
In order to call an instance method, that is, the the methods we were used
to work with until now,
we forced to have previously created an object.
Only then could we call the method on this object.
For example, in order to calculate the surface of a rectangle,
we first need to create a Rectangle-type object.
Only then can we call the calculation of this rectangle's surface.
On the other hand, a class method may very well be called
if not object of the class has been
previously declared.
For example, let " A " be a class with a static method
called "methode1". We may call this method
thanks to the scope resolution operator
without having previously declared any A-type object.
Here, we simply say
that we are calling "method1" of the class "A".
Of course, such an instruction is not valid for non-static methods.
For example, here, in the class "A",
we have a second method : "methode2".
It has not been declared as "static".
If we try to call it only through the name of the class,
without passing by the creation of an instance,
we will get an error.
In order to call the non-static "methode2",
we need an previously declared A-type object
on which to call "methode2".
This is what we are doing here to calculate the surface
of a given rectangle "r".
By the way, please note
that a "static" method method may be called
either through the name of the class
(independently of the any instance's creation,
as we have done here)
or it can be called through an instance
(if such an instance exists).
Therefore, such an instruction is valid
albeit not frequent or recommanded.
Finally, this kind of instruction, accessing a "static" member
through an instance is also possible
for the attributes (if this attribute is accessible, of course).
The fact that a class method may be called independently
of the creation of any instance
begets a few restrictions regarding what we may do within
such a method.
12:02
In languages such as C++, where there is a non-object layer
where we can use usual functions
without passing by the creation of classes,
the use of class methods is warranted only
in very particular situations.
We can imagine, as an example,
the need to create a class method
in order to print a few values of class attributes.
We can imagine the need to define a class method
in order to manipulate class attributes, "static" attributes
who are non constant and private.
In this case, it is necessary to define such methods.
In general, it is almost always preferable to use
usual functions in C++
rather than class methods.
Above, we should absolutely avoid to have "statics" grow rampant
in a program.
Whyso?
Indeed, since a "static" member can be called independently of the creation
of any object, it weakens our oriented-object approach.
Voilà, this concludes our presentation on "static" members
in a class; methods and attributes both.
We have seen that, practically,
most of the "static" attributes we will encounter will be constants.
Also, we should remain careful not to overuse "statics".