next up previous contents index search.gif
Next: 5.4 Properties Up: 5. Classes Previous: 5.2 Class instantiation

Subsections


5.3 Methods

5.3.1 invocation

Method invocaticn for classes is no different than for objects. The following is a valid method invocation:

Var  AnObject : TAnObject;
begin
  AnObject := TAnObject.Create;
  ANobject.AMethod;

5.3.2 Virtual methods

Classes have virtual methods, just as objects do. There is however a difference between the two. For objects, it is sufficient to redeclare the same method in a descendent object with the keyword virtual to override it. For classes, the situation is different: you must override virtual methods with the override keyword. Failing to do so, will start a new batch of virtual methods, hiding the previous one. The Inherited keyword will not jup to the inhherited method, if virtual was used.

The following code is wrong:
\begin{listing}
Type ObjParent = Class
Procedure MyProc; virtual;
end;
ObjChild = Class(ObjPArent)
Procedure MyProc; virtual;
end;
\end{listing}
The compiler will produce a warning:


Warning: An inherited method is hidden by OBJCHILD.MYPROC
The compiler will compile it, but using Inherited can produce strange effects.

The correct declaration is as follows:
\begin{listing}
Type ObjParent = Class
Procedure MyProc; virtual;
end;
ObjChild = Class(ObjPArent)
Procedure MyProc; override;
end;
\end{listing}
This will compile and run without warnings or errors.

5.3.3 Message methods

New in classes are message methods. Pointers to message methods are stored in a special table, together with the integer or string cnstant that they were declared with. They are primarily intended to ease programming of callback functions in several GUI toolkits, such as Win32 or GTK. In difference with Delphi, Free Pascal also accepts strings as message identifiers.

Message methods that are declared with an integer constant can take only one var argument (typed or not):
\begin{listing}
Procedure TMyObject.MyHandler(Var Msg); Message 1;
\end{listing}
The method implementation of a message function is no different from an ordinary method. It is also possible to call a message method directly, but you should not do this. Instead use the TObject.Dispatch method.

The TOBject.Dispatch method can be used to call a message handler. It is declared in the system unit will accept a var parameter which must have at the first position a cardinal with the message ID that should be called. For example:
\begin{listing}
Type
TMsg = Record
MSGID : Cardinal
Data : Pointer;
Var
Msg : TMSg;
\par MyObject.Dispatch (Msg);
\end{listing}
In this example, the Dispatch method will look at the object and all it's ancestors (starting at the object, and searching up the class tree), to see if a message method with message MSGID has been declared. If such a method is found, it is called, and passed the Msg parameter.

If no such method is found, DefaultHandler is called. DefaultHandler is a virtual method of TObject that doesn't do anything, but which can be overridden to provide any processing you might need. DefaultHandler is declared as follows:
\begin{listing}
procedure defaulthandler(var message);virtual;
\end{listing}

In addition to the message method with a Integer identifier, Free Pascal also supports a messae method with a string identifier:
\begin{listing}
Procedure TMyObject.MyStrHandler(Var Msg); Message 'OnClick';
\end{listing}

The working of the string message handler is the same as the ordinary integer message handler:

The TOBject.DispatchStr method can be used to call a message handler. It is declared in the system unit and will accept one parameter which must have at the first position a cardinal with the message ID that should be called. For example:
\begin{listing}
Type
TMsg = Record
MsgStr : String[10]; // Arbitrary length u...
... Data : Pointer;
Var
Msg : TMSg;
\par MyObject.DispatchStr (Msg);
\end{listing}
In this example, the DispatchStr method will look at the object and all it's ancestors (starting at the object, and searching up the class tree), to see if a message method with message MsgStr has been declared. If such a method is found, it is called, and passed the Msg parameter.

If no such method is found, DefaultHandlerStr is called. DefaultHandlerStr is a virtual method of TObject that doesn't do anything, but which can be overridden to provide any processing you might need. DefaultHandlerStr is declared as follows:
\begin{listing}
procedure DefaultHandlerStr(var message);virtual;
\end{listing}

In addition to this mechanism, a string message method accepts a self parameter:
\begin{listing}
TMyObject.StrMsgHandler(Data : Pointer; Self : TMyObject);Message 'OnClick';
\end{listing}
When encountering such a method, the compiler will generate code that loads the Self parameter into the object instance pointer. The result of this is that it is possible to pass Self as a parameter to such a method.

remark: The type of the Self parameter must be of the same class as the class you define the method for.



root
1999-06-10