【问题标题】:How to override a Class property getter in Delphi如何在 Delphi 中覆盖 Class 属性获取器
【发布时间】:2012-06-13 11:00:51
【问题描述】:

我已经定义了一个基类和一些派生类,它们永远不会被实例化。它们只包含类函数和两个类属性。

问题是Delphi要求类属性的属性get方法用static关键字声明,因此不能声明virtual,所以我可以重写它派生类。

所以这段代码会导致编译错误:

    TQuantity = class(TObject)
    protected
      class function GetID: string; virtual; //Error: [DCC Error] E2355 Class property accessor must be a class field or class static method
      class function GetName: string; virtual;
    public
      class property ID: string read GetID;
      class property Name: string read GetName;
    end;

    TQuantitySpeed = class(TQuantity)
    protected
      class function GetID: string; override;
      class function GetName: string; override;
    end;

所以问题是:如何定义一个类属性,其结果值可以在派生类中被覆盖?

使用 Delphi XE2,Update4。

更新: 通过 David Heffernan 的建议使用函数而不是属性解决了这个问题:

    TQuantity = class(TObject)
    public
      class function ID: string; virtual;
      class function Name: string; virtual;
    end;

    TQuantitySpeed = class(TQuantity)
    protected
      class function ID: string; override;
      class function Name: string; override;
    end;

【问题讨论】:

  • 如果IDName 是每个类的常量(getter 方法只返回每个类的常量值),您可以使用Attributes 并使用它们标记类。
  • 这对我来说是一个新概念......开始阅读它,但检索值似乎比仅使用虚拟类方法更复杂
  • 嗯。看来我错了。当我们没有类实例时,很难实现属性(我不知道如何:))。无论如何,看看docwiki.embarcadero.com/RADStudio/en/Attributes_Index 使用属性,您可以使用例如[ID('my class id')][Name('my class name string')] 来注释您的类,然后在运行时为这些类(对象)提取属性值

标签: delphi delphi-xe2


【解决方案1】:

如何定义一个类属性,其结果值可以在派生类中被覆盖?

您不能,正如编译器错误消息所表明的那样:

E2355 类属性访问器必须是类字段或类静态方法

类字段在通过继承相关的两个类之间共享。所以这不能用于多态性。而且类静态方法也不能提供多态行为。

使用虚拟类函数而不是类属性。

【讨论】:

  • 所以我应该创建另一个虚拟类函数,并从 Class-property get 方法中调用它?
  • @Bascy 是的,这将是最简单的解决方案。
  • @DavidHeffernan 我没有正确阅读您的解决方案,我现在明白了,只是定义了一个公共类方法 ID:string;虚拟的;
  • 类静态方法可以调用虚拟类方法,但不会获得多态行为,因为它是静态的。所以我能看到的唯一解决方案是一个普通的类虚函数而不是一个属性。
  • 哦,我明白了。静态类方法根本没有对类的引用(Self) - 正是你所说的,我只是不明白。看起来真的很可惜!
【解决方案2】:
type
  // Abstraction is used at sample to omit implementation
  TQuantity = class abstract
  protected
    class function GetID: string; virtual; abstract;
    class procedure SetID(const Value: string); virtual; abstract;
  public
    // Delphi compiler understands class getters and setters
    {class} property ID: string read GetID write SetID;
  end;

var
  Quantity: TQuantity;

begin
  Quantity.ID := '?';

【讨论】:

    猜你喜欢
    • 2015-08-18
    • 2011-11-06
    • 2014-02-21
    • 2013-12-04
    • 2014-01-17
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多