【问题标题】:Constant class instance常量类实例
【发布时间】:2010-12-28 14:35:18
【问题描述】:

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

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

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

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

【问题讨论】:

  • 您可以使用编辑器中的 101010 按钮将文本格式化为代码。
  • 从未见过这样的按钮!!?它在哪里?
  • 编辑工具栏中的第五个按钮。
  • 好吧....我有Delphi 2010,似乎甚至没有编辑工具栏-工具栏选项编辑器似乎没有为任何工具栏提供这样的按钮。我错过了什么,还是在这个版本中发生了变化?
  • tony,我们说的是 stackoverflow 编辑器工具栏,当您编写问题或答案时,它位于编辑器字段上方。

标签: delphi class constants instance-variables


【解决方案1】:

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

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

一)

  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 的现有方面已经满足的内容。

【讨论】:

  • 非常感谢所有这些 - 非常有帮助。重新转换,是的,我模糊地意识到这一点,但我在这里勾勒出一个本体,而不是对单元到单元的转换本身特别感兴趣——它们只是作为本体要求的一部分出现。
【解决方案2】:

尝试只读属性:

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);

【讨论】:

  • 谢谢 - 这似乎照顾了只读要求 t
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 2014-10-18
    • 2020-11-30
    • 2014-09-21
    • 1970-01-01
    • 2017-11-11
    相关资源
    最近更新 更多