常量类实例

发布于 2024-08-15 17:05:33 字数 309 浏览 3 评论 0原文

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

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

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

我需要执行类似的操作,其中 Tunit 是一个,meter 是一个实例类,但它是一个(特定)实例,其关联字段不能被其他代码更改。 我不知道如何实现这一目标。有什么想法吗?

If I define a record, I can define an instance of that record as a constant record e.g.

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

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

I need to do something similar where Tunit is a Class and metre is an instance of the class, but is a (particular) instance whose associated fields cannot be changed by other code.
I cannot see how to achieve this. Any ideas please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甲如呢乙后呢 2024-08-22 17:05:33

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

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

a)

  interface

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

   :

  implementation

   :

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

  finalization
    FreeAndNIL(metre);

  end.

注意:如果您的类只是问题中出现的数据容器,那么您可能会考虑省略终结释放 - 尽管技术上存在内存泄漏,但您可以实际上不会泄漏任何内容,因为当您的应用程序进程终止时,您的实例使用的内存将被回收。如果项目中的其他最终化代码在释放后访问计量实例,则最终化中的释放可能会导致问题。

我还警告您不要尝试使用任何所谓的“单例”类。在像这样的简单情况下,它们增加了复杂性和开销,但收益为零。

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

There are two ways to achieve something similar, depending on your needs:

The first way involves initialising an instance of your class either in a unit initialization procedure (remembering to Free the instance in the corresponding finalization procedure) or using an accessor unit function to initialise the instance on first access:

a)

  interface

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

   :

  implementation

   :

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

  finalization
    FreeAndNIL(metre);

  end.

NOTE: If your class is simply a container for data as it appears from your question then you might consider omitting the finalization Free'ing - although technicall a memory leak, you won't actually leak anything as the memory used by your instance will be reclaimed when your app process terminates. Free'ing in finalization might cause issues if other finalization code in your project accesses the metre instance after it has been free'd.

I'd also caution you against trying to use any so called "singleton" classes. They add complexity and overhead for zero benefit in such simple cases as this.

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.

The same observations w.r.t the optionality of finalization apply in this case also.

Note also that if performance is a significant concern and this accessor function is likely to be used a lot then you can take further steps to optimise this area, using a function pointer initialised to a factory function initially, which replaces itself with a pointer to a simple unconditional accessor function upon first access.

The second way to achieve it is to use class functions to return fixed values from a specially derived class, rather than using member data. You don't then need to instantiate the class at all and do not need to worry about disposing of it either. I can't remember off the top of my head if Delphi 2010 now supports class variables as well as class functions - if it does then that may be an answer too. But if you aren't using Delphi 2010 then the question would be moot anyway.

It would look a little something like:

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

etc

I do wonder however... are you aware of the Standard Conversions unit and associated units of measure functionality? I only ask because the content in this question looks like it might be something that is already catered for by an existing aspect of the Delphi RTL.

青柠芒果 2024-08-22 17:05:33

尝试只读属性:

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

try readonly properties:

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);
握住你手 2024-08-22 17:05:33

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

While it would be technically possible to create constant object values, that concept would be incompatible with normal memory deallocation methods, and Delphi/native does not support it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文