Class Delphi 2009:组件对象属性默认值
如何设置组件对象属性值的默认值 组件类别代码:Class Delphi 2009:组件对象属性默认值,class,delphi,properties,components,delphi-2009,Class,Delphi,Properties,Components,Delphi 2009,如何设置组件对象属性值的默认值 组件类别代码: unit CustomClass; interface uses Classes; type TCustomClass = class; TConfiguration = class; TCustomClass = class (TComponent) private FConfiguration: TConfiguration; procedure SetConfiguration(const V
unit CustomClass;
interface
uses
Classes;
type
TCustomClass = class;
TConfiguration = class;
TCustomClass = class (TComponent)
private
FConfiguration: TConfiguration;
procedure SetConfiguration(const Value: TConfiguration);
published
property Configuration: TConfiguration read FConfiguration write SetConfiguration;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
TConfiguration = class (TPersistent)
private
FDelay: Integer;
FSize: Integer;
procedure SetDelay(const Value: Integer);
procedure SetSize(const Value: Integer);
published
property Delay: Integer read FDelay write SetDelay;
property Size: Integer read FSize write SetSize;
public
procedure Assign(Source: TPersistent); override;
end;
implementation
{ TCustomClass }
constructor TCustomClass.Create(AOwner: TComponent);
begin
inherited;
Configuration.FileName:= 'FileName';
Configuration.Size := 10;
end;
destructor TCustomClass.Destroy;
begin
Configuration.Free;
inherited;
end;
procedure TCustomClass.SetConfiguration(const Value: TConfiguration);
begin
FConfiguration.Assign(Value);
end;
{ TConfiguration }
procedure TConfiguration.Assign(Source: TPersistent);
begin
inherited;
Delay := (Source as TConfiguration).Delay;
Size := (Source as TConfiguration).Size;
end;
procedure TConfiguration.SetDelay(const Value: Integer);
begin
FDelay := Value;
end;
procedure TConfiguration.SetSize(const Value: Integer);
begin
FSize := Value;
end;
end.
在我的IDE中,它将显示为修改了对象属性(蓝色粗体)
我认为在TConfiguration类属性上设置默认函数和存储函数时,如下所示:
t配置
interface
private
function FileNameStored: Boolean;
published
property FileName: string read FFileName write SetFileName stored FileNameStored;
property Size: Integer read FSize write SetSize default 10;
implementation
function TConfiguration.FileNameStored: Boolean;
begin
Result := FileName <> 'FileName';
end;
接口
私有的
函数FileNameStored:Boolean;
出版
属性文件名:字符串读取FFileName写入SetFileName存储FileNameStored;
属性大小:整数读取FSize写入SetSize默认值10;
实施
函数TConfiguration.FileNameStored:Boolean;
开始
结果:=文件名'FileName';
结束;
它将TConfiguration的属性涂成普通蓝色,但不是TCustomClass的配置属性,我不想在TCustomClass上设置其默认值,因为TConfiguration可能会在其他组件中使用
然后我还想,
TCustomClass
interface
private
function ConfigurationStored: Boolean;
published
property Configuration: TConfiguration read FConfiguration write SetConfiguration stored ConfigurationStored;
implementation
function TCustomClass.ConfigurationStored: Boolean;
begin
Result := Configuration.FileName <> 'FileName' and
Configuration.Size <> 10;
end;
接口
私有的
函数配置存储:布尔;
出版
属性配置:TConfiguration read FConfiguration write SetConfiguration storaged Configuration;
实施
函数TCustomClass.ConfigurationStored:布尔值;
开始
结果:=Configuration.FileName“FileName”和
配置。尺寸10;
结束;
但是,这仅将TCustomClass配置属性颜色设置为普通蓝色,而不是其属性
回答
正如@RemyLebeau指出的(在第一个和最上面的答案中),代码中存在错误。
在这种情况下,我决定不为属性设置任何默认值。代码中有几个错误
TCustomClass
构造函数没有创建TConfiguration
对象。您需要添加以下内容:
constructor TCustomClass.Create(AOwner: TComponent);
begin
inherited;
FConfiguration := TConfiguration.Create; // <-- add this
FConfiguration.FileName := 'FileName';
FConfiguration.Size := 10;
end;
t配置.Assign()
方法实现不正确。通过在复制值之前调用继承的Assign()
方法,如果调用方将一个t配置
对象分配给另一个,则代码在运行时将始终引发EConvertError
异常。原因是基类TPersistent.Assign()
实现只调用Source.AssignTo(Self)
,而TConfiguration
没有覆盖AssignTo()
方法,因此调用TPersistent.AssignTo()
,它只调用Dest.AssignError(Self)
,这引发了一个例外。因此,如果源
实际上是t配置
对象,则不要调用继承的Assign()
方法:
procedure TConfiguration.Assign(Source: TPersistent);
begin
if Source is TConfiguration then
begin
FDelay := TConfiguration(Source).Delay;
FSize := TConfiguration(Source).Size;
end else
inherited;
end;
TCustomClass
配置
属性颜色设置为普通蓝色,而不是其属性
这是故意的。A仅适用于为其指定的属性
将类与窗体上的TFont
属性进行比较。当ParentFont
为True
时,将不会存储Font
属性。但是它的成员Color
和Name
仍然不是默认的,因此它们看起来好像将被存储。这是因为TFont
对象不知道其所有者,它怎么可能知道?一次是画布的一部分,另一次是控件的一部分,或者根本没有所有者。在所有这些条件下,TFont
对象应该是完全功能的,因此它不会询问其父对象应该如何操作。另一方面:父母也不应该询问孩子如何表现
现在回到您的场景:是否需要存储
FileName
和Size
属性应该在TConfiguration
中处理。是否应存储TCustomClass
的Configuration
属性可能不取决于这些FileName
和Size
属性。如果存储了配置
属性(粗体),但未存储其所有成员(非粗体),则最后不会存储任何内容。如果您有一个ParentConfiguration
属性,就像ParentFont
一样,您可以决定不存储Configuration
属性。否则,就别管它了,不要让粗体进一步分散您的注意力。为什么我要将TConfiguration赋值从TCustomClass构造函数移到TConfiguration构造函数?这是编写组件类的常规方法吗?因为如果将来我创建另一个组件并使用相同的TConfiguration类,该怎么办?类的属性是该类的一个特征。该属性的默认值也是。这理由已经足够了。但特别是当您需要在多个场景中使用该类时,您应该将其设计为能够自主运行。因此,您可以在需要的类中创建一个t配置
,并在其中分配自定义设置,但默认设置是在t配置
本身中进行的。这完全取决于您。如果一个绿色的苹果在果篮里需要是红色的,那么在装满果篮的时候把它变成红色。但是如果一个绿色的苹果应该有红色的斑点,那么你应该在做篮子之前设计一个有斑点的苹果。或者:如果篮子里装的是哪种类型的香蕉无关紧要,那么在装满篮子后登记香蕉类型。但是,当篮子中可能只有Chiquita香蕉时,则通过从TBanana设计一个TChiquitaBanana专门用于此类型篮子的TChiquitaBanana来实施该限制。您是否打算将配置对象放到窗体上,并将自定义类放到窗体上,然后连接它们?或者您希望配置对象是属于自定义类的属性,而不必手动创建和分配?然后您确实忽略了一些显而易见的事情,正如Remy指出的那样。他表明你需要解释
procedure TConfiguration.Assign(Source: TPersistent);
begin
if Source is TConfiguration then
begin
FDelay := TConfiguration(Source).Delay;
FSize := TConfiguration(Source).Size;
end else
inherited;
end;