如果我定义一个记录,我可以将该记录的一个实例定义为一个常量记录,例如
Tunit = record
_name: string;
_scale: real;
end;
const metre: Tunit =
(_name: 'metre';
_scale: 1.0;
)
我需要做类似的事情,其中 Tunit 是一个类,而仪表是该类的一个实例,但它是一个(特定)实例,其关联字段不能被其他代码更改。我看不出如何实现这一目标。请问有什么想法吗?
如果我定义一个记录,我可以将该记录的一个实例定义为一个常量记录,例如
Tunit = record
_name: string;
_scale: real;
end;
const metre: Tunit =
(_name: 'metre';
_scale: 1.0;
)
我需要做类似的事情,其中 Tunit 是一个类,而仪表是该类的一个实例,但它是一个(特定)实例,其关联字段不能被其他代码更改。我看不出如何实现这一目标。请问有什么想法吗?
有两种方法可以实现类似的效果,具体取决于您的需要:
第一种方法涉及在单元初始化过程中初始化类的实例(记住在相应的终结过程中释放实例)或使用访问器单元函数在首次访问时初始化实例:
一个)
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 的现有方面所满足。
尝试只读属性:
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);
虽然在技术上可以创建常量对象值,但该概念与正常的内存释放方法不兼容,并且 Delphi/native 不支持它。