我正在创建一个小型RPG引擎。我刚刚开始为游戏的对象实现一个类树,我不能100%确定我应该在哪里以及在什么情况下使用哪些方法指令。
我查看过Free Pascal Complier的参考指南和其他各种互联网资源,但我仍然不自信。
我计划实现游戏对象处理的方式要求游戏对象的类别有一个共同的基类,并存储在该类的数组中,从而将它们作为祖先投射。
我主要需要了解的是如何确保当我将一个类转换为其中一个祖先时,它调用实际类的重载/重写/重新引入的方法而不是祖先的方法。
谢谢你的时间!
如果我不够清楚,我很乐意在这里澄清/重新说一句。
答案 0 :(得分:4)
当你将它们放入父类的数组中时,你不会“投射”,你不应该这样做;这不是继承和多态如何工作。
您在父级(祖先)中创建一个虚方法,然后每个子级继承父级的方法并使用自己的特定行为覆盖它。当您调用父方法时,多态性可确保调用正确的方法。
这是一个快速(微不足道)的例子,说明应该如何构建这样的东西。它是控制台应用程序的形式,因此您可以实际运行它以查看输出。
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
// Base class
TAnimal=class
procedure Sit; virtual; // Virtual keyword *necessary* for things to work
procedure Speak; virtual;
end;
// Descendent classes
TDog=class(TAnimal)
procedure Sit; override; // Override keyword required here
procedure Speak; override;
end;
TCat=class(TAnimal)
// No implementation of Sit, because cats don't sit on command
procedure Speak; override; // Override required here also
end;
// Array type to hold them, so we don't have to typecast anything
TAnimalArray = array of TAnimal;
// Implementation of classes
{ TAnimal }
procedure TAnimal.Sit;
begin
end;
procedure TAnimal.Speak;
begin
// Parent does nothing
end;
{ TCat }
procedure TCat.Speak;
begin
inherited;
WriteLn('Meow.');
end;
{ TDog }
procedure TDog.Sit;
begin
inherited;
WriteLn('Sitting down now.');
end;
procedure TDog.Speak;
begin
inherited;
Writeln('Woof! Woof!');
end;
// Test code to demonstrate use of inheritance and polymorphism
var
Animals: TAnimalArray;
i: Integer;
Pet: TAnimal; // Variable that holds parent type (TAnimal)
const
NumberOfAnimals = 5;
begin
SetLength(Animals, NumberOfAnimals);
// Fill array with a mix of both dogs and cats
for i := 0 to High(Animals) do
begin
if Odd(i) then
Animals[i] := TDog.Create
else
Animals[i] := TCat.Create;
end;
// Loop to use each one regardless of which type, by just accessing the
// virtual Speak method they overrode from their parent class
for Pet in Animals do
begin
Pet.Speak;
Pet.Sit; // Call method only defined for TDog
end;
WriteLn(''); // Blank line in console to separate loops.
// If FreePascal doesn't support the enumeration (for..in) method, do it
// using a counter:
for i := 0 to High(Animals) do
begin
Animals[i].Speak;
Animals[i].Sit; // Call method only defined for TDog
end;
// In real life code, you'd loop through the array and free each one here.
// In this test code, we're exiting right away, and there's really no point
Readln;
end.
以上产生输出:
Meow.
Woof! Woof!
Sitting down.
Meow.
Woof! Woof!
Sitting down.
Meow.
Meow.
Woof! Woof!
Sitting down.
Meow.
Woof! Woof!
Sitting down.
Meow.
您可以在docwiki找到有关Delphi实施OOP的相当完整的讨论。虽然它不是FreePascal,但大部分都是兼容的,所以它应该有点等同。我不知道任何类似FPC的文档。