常量类实例

时间:2009-12-21 01:25:49

标签: delphi class constants instance-variables

如果我定义一条记录,我可以将该记录的实例定义为常量记录,例如

Tunit = record
  _name: string;
  _scale: real;
end;

const metre: Tunit =
  (_name: 'metre';
   _scale: 1.0;
  )

我需要做类似的事情,其中​​Tunit是 Class ,而meter是该类的实例,但是(特定)实例的关联字段不能被其他代码更改。 我看不出如何实现这一目标。有什么想法吗?

3 个答案:

答案 0 :(得分:4)

根据您的需要,有两种方法可以实现类似

第一种方法是在单元初始化过程中初始化类的实例(记住在相应的终结过程中释放实例)或使用访问器单元函数在第一次访问时初始化实例:

A)

  interface

  var
    metre : TUnit = NIL;  // Can initialise a unit variable

   :

  implementation

   :

  initialization
    metre := TUnit.Create( ... );

  finalization
    FreeAndNIL(metre);

  end.

注意:如果您的类只是一个数据容器,因为它出现在您的问题中,那么您可能会考虑省略最终化Free'ing - 尽管技术内存泄漏,您实际上不会泄漏任何内容作为您使用的内存当您的应用程序进程终止时,将回收实例。如果项目中的其他终结代码在被免费后访问了仪表实例,那么在最终确定中自由可能会导致问题。

我也提醒你不要试图使用任何所谓的“单身”类。在如此简单的情况下,它们增加了复杂性和开销以实现零利益。

b)中

  interface

    function Metre: TUnit;

  implementation

  var
    _metre : TUnit = NIL;  // Can initialise a unit variable


  function Metre: TUnit;
  begin
    if NOT Assigned(_metre) then
      _metre := TUnit.Create( ... );

    result := _metre;
  end;


  finalization
    FreeAndNIL(metre);

  end.

同样的观察结果,在这种情况下,最终确定的可选性也适用。

另请注意,如果性能是一个重要问题,并且此访问器函数可能会被大量使用,那么您可以采取进一步的步骤来优化此区域,使用最初初始化为工厂函数的函数指针,将其替换为第一次访问时指向简单的无条件访问器函数。

实现它的第二种方法是使用类函数从特殊派生类返回固定值,而不是使用成员数据。然后,您根本不需要实例化该类,也不需要担心处理它。如果Delphi 2010现在支持类变量以及类函数,我记不清了我的头脑 - 如果确实如此,那么这也可能是一个答案。但是如果你没有使用Delphi 2010,那么这个问题无论如何都会毫无意义。

看起来有点像:

TMetre = class(TUnit)
  class function Name: String; override;
  class function Scale: Double; override;
end;

我确实不知道......您是否了解标准转换单元和相关的度量单位功能?我只是问,因为这个问题的内容看起来可能已经被Delphi RTL的现有方面所迎合了。

答案 1 :(得分:4)

尝试只读属性:

interface
type
  TUnit = class
  private
     _name: string;
     _scale: real;
     class function makeunit(aname: string; ascale: real): TUnit;
  public 
     property name: string read _name;
     property scale: real read _scale;
  end;

function metre: TUnit;

implementation

var
  _metre : TUnit = nil;

class function TUnit.makeunit(aname: string; ascale: real): Tunit;
begin
  Result._name := aname;
  Result._scale := ascale;
end;

function Metre: TUnit;
begin
  if not Assigned(_metre) then
    _metre := TUnit.makeunit('metre', 1.0);
  result := _metre;
end;

finalization
  FreeAndNIL(_metre);

答案 2 :(得分:0)

虽然在技术上可以创建常量对象值,但这个概念与普通的内存释放方法不兼容,而且Delphi / native不支持它。