【问题标题】:Pascal passing object of inheritance class to procedurePascal将继承类的对象传递给过程
【发布时间】:2020-04-15 18:34:07
【问题描述】:

我的类型声明为:

TPlayer = class(TObject) 
TBullet = class(TObject) 
TEnemy = class(TObject)   

和对象:

Player: TPlayer;
PlayerBullets: Array[1..20] of TBullet;
Enemies: Array[1..20] of TEnemy;
EnemyBullets: Array[1..20] of TBullet;

现在我想创建 TBullet 构造函数,它可以处理来自玩家和敌人的信息。简而言之,我希望这个构造函数同时处理 TPlayer 和 TEnemy 对象。

我的想法是:

constructor TBullet.Create(const Source: TObject);

很遗憾,它不起作用。如何做到这一点?

编辑: 我的确切问题是:当我将 TPlayer 或 TEnemy 对象传递给此构造函数时,它看不到这些对象的属性。例如:TPlayer 有 attr xPos。如果我使用 Bullet.Create(Player) 并在 TBullet.Create 中使用 Source.xPos,我会收到错误消息。

【问题讨论】:

  • 这在什么意义上不起作用?您可以将任何类的实例传递给TBullet.Create。如果您需要帮助,您需要付出更多努力来解释您的问题、您想要实现的目标、您尝试了什么以及它是如何失败的。

标签: lazarus freepascal


【解决方案1】:

我可以想到 3 种方法来实现这一目标。

  1. 让 TPlayer 和 TEnemy 都派生自同一个基类,这些基类具有 TBullet 的构造函数所需的所有信息,并具有该类型的构造函数参数。
  2. 定义一个包含 TBullet 所需信息的接口,并让 TPlayer 和 TEnemy 实现该接口
  3. 保持一切“原样”并在 TBullet 的构造函数中以“硬编码”方式管理不同的类。

我的意思是:

constructor TBullet.Create(const Source: TObject);
var 
  vPlayer : TPlayer;
  vEnemy : TEnemy;
begin
  if Source is TPlayer then
  begin
    vPlayer := TPlayer(Source);
    [Do whatever with vPlayer]
  end else if Source is TEnemy then
  begin
    vEnemy := TEnemy(Source);
    [Do Whatever with vEnemy]
  end;
end;

哪种解决方案最好?这本身可能是一场辩论,很大程度上取决于您的具体情况。仅根据您的班级名称,我猜选项 1 可能是有效的。可以创建“TCharacter”类并将其用作 TCharacter 和 TEnemy 的基础类。但这只是目前的猜测。

【讨论】:

【解决方案2】:

在 Windows 中,使用通用方法从父级继承(在父级中可能是抽象的)或实现接口(当再次可以自定义行为时)几乎没有区别。 如果您有一个枚举 commonParticipant(cpPlayer, cpEnemy),则 Windows 允许访问最终父级 IUnknown,然后再次向下访问一个子接口,该接口标识该子级特有的方法,即您可以传递一个包含 commonParticipant 的 ICommonParticipant,然后使用iPlayer 或 IEnemy 界面

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    • 1970-01-01
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多