Short answer: because that's how Delphi did it.
Long answer: Delphi used the same syntax that is used for static methods inside classes also for records. In classes you either have a class method using class procedure or class function (which takes the class type as Self parameter and can also be virtual) or a static class method if you append the static modifier (in which case there is no Self). Now, Delphi doesn't really acknowledge object at all (considering it deprecated and such) and thus they simply used the syntax they know to also implement it for records when they implemented advanced records.
By the way: the correct syntax in an object declaration is without the class keyword, but with the static modifier. That is because the object type stems from a time before classes were introduced, thus also before the introduction of the class keyword. FPC also allows the syntax from the class type simply because both objects and classes share a lot of code and sometimes objects gain functionality introduced for classes simply by accident.
Thanks PascalDragon,
although I still do not find it a complete answer.
The short answer is clear, but that would lead to two second questions:
- why did Delphi do it like this? I know it is beyond this forum to guess, but Embarcadero guys are also very smart, so surely they had either a good reason or a history behind.
- why is it the same in every mode? If you see the still open Q1 I had earlier, I feel a bit of confusion among compiler modes and modeswitches, but what is clear that different modes can accept or reject different syntax. So, even if it is the case in mode
delphi, I do not see why it is still the same in mode
objfpc + modeswitch
advancedrecords.
From the long answer I again learnt something, that the
class keyword only appeared with the
class type and since
object is older than
class, object should not use the
class procedure type definition. Btw. I use in my doc the terms "class level field, class level method", even in
object. I hope it is still the correct terminology.
Also your long answer leads us to my third question:
Q3. Why does a
static method in an
object has
Self?
I did not find any documentation for
object, but I found it for
class, where it states what you also write, i.e. that the
static keyword makes the call without Self. It is impossible to test
static alone for
class, as
class does not allow only
static without
class in front of
procedure. When
class procedure X; is used then it has Self, but with
static; added it has not got Self. But this is almost my Q4 later, so back to
object and Q3:
In
object (chapter 5.3 in my doc) all the four definitions are possible (I only write
procedure, but also
function works the same).
procedure PNothing;
procedure PStatic; static;
class procedure PClass;
class procedure PClassStatic; static;
The first is easy, but the other three are all some sort of class level methods. Based on the logic described above for
class, I would expect that here (i.e.
object) the two with the
static; keyword have no Self. But it is not the case; PStatic happily has a Self, only the last one is without.
My expectation was that using the
class procedure part makes it callable as
tMyObject.P, while if
class is not in front of it then only
MyObject.P can be called, while using or not
static; makes only the list of arguments different with or without Self, but it is not the case. Is it a bug?
Last, this also contradicts a bit to your answer regarding the "correct syntax". If one only uses (I am still at
object!) the PStatic method from above as you suggest, then one cannot use the tMyObject.P logic, what might be handy sometimes, e.g. if we do not want to make an instance at all (equivalent of making sure that regardless how many instances are declared they all behave as the same one, i.e. only class level fields and methods are declared).
So my - might be wrong - conclusion is that for
object the best is to use
class procedure PClass;, for class level methods. PClass has a benefit over PStatic as it can be called from the type, while PStatic cannot AND PClass also has a benefit over PClassStatic as it always has a Self, even if we do not want to use. Is it a wrong assumption?