From the previous material, readers learned that the functioning of objects is provided by various types of methods that differ in the features of the implementation of the inheritance mechanism. Now it is time to look at these methods in more detail.
Abstract methods are methods that are defined in a class but do not contain any actions, are never called, and must necessarily be overridden in the descendants of the class. Only virtual and dynamic methods can be abstract. In Object Pascal, such methods are declared using a directive of the same name. It is indicated when describing the method:
procedure NeverCallMe; virtual; abstract;
You don't need to write any code for this method. Calling the NeverCallMe method will create an EAbstractError exception (chapter 4 for exceptions).
An example with the TField class from sections. The "polymorphism" of this chapter explains why the use of abstract methods is necessary. In this case, the TField class is not used by itself; its main purpose is to be the ancestor of the hierarchy of specific classes - "fields" and to give the opportunity to abstract from particulars. Although the showData procedure parameter is described as a TField, if you pass an object of this class to it, an abstract method call exception occurs.
Static methods, as well as any fields in child objects, behave in the same way: you can overlap old names without restriction and at the same time change the type of methods. The code of the new static method completely overlaps (replaces) the code of the old method:
type TlstObj = class i: Extended; procedure SetData(AValue: Extended); end; T2ndObj = class (TlstObj) i: Integer; procedure SetData(AValue: Integer); end; procedure TlstObj.SetData; begin i: = 1.0; end; procedure T2ndObj.SetData; begin i: = 1; inherited SetData (0.99); end;
In this example, different methods named SetData assign values to different fields named i. The overlapping (eponymous) ancestor field is not available in the descendant; so, of course, the two fields of the same name with the name i are nonsense; this is just an example.
In programming practice, it is common to give all identifiers in a program (including object fields) meaningful names, which will make it much easier to work with the source code not only for other developers, but also for you.
Unlike a field, within other methods, the overlay method is available when you specify the inherited reserved word. By default, all object methods are static—their address is determined at the compilation stage of the project, so they are called the fastest. Maybe it's not yet clear to the reader why this fact is mentioned. Just remember it, you will need it when comparing static and virtual methods.
Virtual and dynamic methods are fundamentally different from static methods. They must be declared by adding the appropriate virtual or dynamic directive. Both of these categories existed in previous versions of the Pascal language. In terms of inheritance, the methods of these two kinds are the same: they can only be overridden in a child class by methods of the same type.
If you think about the example above, it is clear that the compiler does not have the ability to determine the class of the object actually passed to the showData procedure. You need a mechanism to determine this at run time. This mechanism is called late binding.
Naturally, this mechanism must be somehow connected to the transmitted object. To do this, use the Virtual Method Table (VMT) and the Dynamic Method Table (DMT).
The difference between virtual and dynamic methods lies in the peculiarities of address search. When the compiler encounters a call to a virtual method, it substitutes code instead of a direct call to a specific address that accesses VMT and retrieves the desired address from there.
There is such a table for each class (object type). It stores the addresses of all virtual methods of a class, regardless of whether they are inherited from an ancestor or overlapped in that class. Hence the advantages and disadvantages of virtual methods: they are called relatively quickly, but a large amount of memory is required to store pointers to them in the VMT table.
Dynamic methods are called more slowly, but allow you to use memory more economically. Each dynamic method is assigned a unique index by the system. The dynamic method table of a class stores the indexes and addresses of only the dynamic methods that are described in the class. When a dynamic method is called, this table is searched; in case of failure, the DMT tables of all ancestor classes are viewed in the order of the hierarchy and, finally, the TObject class, where there is a standard handler for calling dynamic methods. The memory savings are obvious.
To overlay both virtual and dynamic methods, the override directive is used, with which (and only with it!) you can override both of these types of methods. Here's an example:
type TFirstClass = class FMyFieldl: Integer; FMyField2: Longint; procedure StatMethod; procedure VirtMethodl; virtual; procedure VirtMethod2; virtual; procedure DynaMethodl; dynamic; procedure DynaMethod2; dynamic; end; TSecondClass = class(TMyObject) procedure StatMethod; procedure VirtMethodl; override; procedure DynaMethodl; override; end; var Objl: TFirstClass; Obj2: TSecondClass;
The first of the methods in the example is recreated, the other two overlap. Attempting to apply the override directive to a static method will cause a compilation error.
Be careful: attempting to overlay with a directive that is not override, but virtual or dynamic will actually create a new method of the same name.