Someone who reads this code could be under the impression
that they are working with "String"s and expect a certain
behavior for the substring method
and this behavior would not actually be present
because of this override.
In order to avoid this sort of effects, you should set the behavior
of a class by declaring it as "final", as done in the case of the String class.
This fail-safe does make us lose some liberties that could
be interesting; for example, the extension programmer could
chose to redefine the substring method by improving its algorithm
and preserving its semantics, meaning that the behavior would be identical
to that of the String class. Unfortunately,
this would not be possible, since the "String" class is "final".
There, now you know the meaning of the "final" keyword
when it applies to a method or to a class.
You probably also know it for variables.
We will come back to this point mainly when variables
contain a reference to an object.
The "final" modifier can also be applied to variables,
whether they are local variables,
method parameters or what we call "instance variables",
i.e class attributes.
It is then impossible to assign a value more than once
to this variable.
In the specific case where it is an attribute that is final,
then it can be initialized
in the constructor of the class, but it cannot be modified
later on.
For example if, in a given class, we define