Jump to content

Respond to an unknown method call: Difference between revisions

→‎{{header|Object Pascal}}: complete replacement of the example
m (syntax highlighting fixup automation)
(→‎{{header|Object Pascal}}: complete replacement of the example)
Line 891:
 
=={{header|Object Pascal}}==
Works with FPC(tested with version 3.2.2).
{{incorrect|Object Pascal|Fails to meet at least two requirements. 1) Defining an abstract method constitutes predefining the method; bark is not an unknown method, but a known, unimplemented method. 2) The animal object isn't handling the situation; the caller gets an exception.}}
 
The example uses the late binding mechanism provided by custom variants. This will require some boilerplate code that needs to be placed in a separate unit:
An exception about calling a virtual method will be raised and interrupt the current code flow. But in that situation, the function is actually known. The concept of a function not being known at all does not exist in Object Pascal, due to static name lookup checking. That is to say, the call a.b() causes the compiler to verify that the symbol b exists in the namespace associated with expression a, and refers to a function.
<syntaxhighlight lang="pascal">
unit MyObjDef;
{$mode objfpc}{$h+}
interface
 
uses
To avoid the possibility of an abstract method call, one common solution is to leave an empty implementation for the virtual method instead of making it abstract. This is what an abstract method call looks like:
SysUtils, Variants;
 
function MyObjCreate: Variant;
<syntaxhighlight lang="pascal">
type
Tanimal = class
public
procedure bark(); virtual; abstract;
end;
 
implementation
 
var
MyObjType: TInvokeableVariantType;
animal: Tanimal;
 
type
TMyObjType = class(TInvokeableVariantType)
procedure Clear(var V: TVarData); override;
procedure Copy(var aDst: TVarData; const aSrc: TVarData; const Indir: Boolean); override;
function GetProperty(var aDst: TVarData; const aData: TVarData; const aName: string): Boolean; override;
end;
 
function MyObjCreate: Variant;
begin
Result := Unassigned;
TVarData(Result).VType := MyObjType.VarType;
end;
 
procedure TMyObjType.Clear(var V: TVarData);
begin
V.VType := varEmpty;
end;
 
procedure TMyObjType.Copy(var aDst: TVarData; const aSrc: TVarData; const Indir: Boolean);
begin
VarClear(Variant(aDst));
aDst := aSrc;
end;
 
function TMyObjType.GetProperty(var aDst: TVarData; const aData: TVarData; const aName: string): Boolean;
begin
Result := True;
case LowerCase(aName) of
'bark': Variant(aDst) := 'WOF WOF!';
'moo': Variant(aDst) := 'Mooo!';
else
Variant(aDst) := Format('Sorry, what is "%s"?', [aName]);
end;
end;
 
initialization
animalMyObjType := TanimalTMyObjType.Create;
finalization
animalMyObjType.Free;
end.
</syntaxhighlight>
 
And main program:
animal := Tanimal.Create;
<syntaxhighlight lang="pascal">
animal.bark(); // abstract method call exception at runtime here
program Test;
animal.Free;
{$mode objfpc}{$h+}
uses
MyObjDef;
 
var
MyObj: Variant;
 
begin
MyObj := MyObjCreate;
WriteLn(MyObj.Bark);
WriteLn(MyObj.Moo);
WriteLn(MyObj.Meow);
end.
</syntaxhighlight>
{{out}}
<pre>
WOF WOF!
Mooo!
Sorry, what is "Meow"?
</pre>
 
=={{header|Objective-C}}==
73

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.