2

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

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

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

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

4

3 回答 3

4

有两种方法可以实现类似的效果,具体取决于您的需要:

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

一个)

  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;

ETC

但是我确实想知道...您是否知道标准转换单位和相关的度量单位功能?我之所以问,是因为这个问题中的内容看起来可能已经被 Delphi RTL 的现有方面所满足。

于 2009-12-21T02:46:09.133 回答
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);
于 2009-12-21T03:47:16.617 回答
0

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

于 2009-12-22T06:40:07.530 回答