首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >组件下的属性显示错误

组件下的属性显示错误
EN

Stack Overflow用户
提问于 2017-04-27 08:02:32
回答 2查看 65关注 0票数 2

我想创建一个结构如下的组件:

代码语言:javascript
复制
type
  TCustomMyComp = class;
  TMyComp = class;
  TCustomSqlCommands = class;
  TSqlCommands = class;
  TFields = class;
  TFieldsItem = class;
  TFieldsSqlCommands = class;

 TCustomMyComp = class(TComponent)
  private
    FFields: TFields;
    FSqlCommands: TSqlCommands;
    procedure SetFields(Value: TFields);
    procedure SetSqlCommands(Value: TSqlCommands);
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Fields: TFields read FFields write SetFields;
    property SqlCommands: TSqlCommands read FSqlCommands write SetSqlCommands;
  end;

TCustomSqlCommands = class(TPersistent)
  private
    FOwner: TCustomMyComp;
    FSelect: TStrings;
    FInsert: TStrings;
    FUpdate: TStrings;
    FDelete: TStrings;
    procedure SetSql(Index: Integer; Value: TStrings);
  public
    constructor Create(AOwner: TCustomMyComp); virtual;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    property Select: TStrings index 0 read FSelect write SetSql;
    property Insert: TStrings index 1 read FInsert write SetSql;
    property Update: TStrings index 2 read FUpdate write SetSql;
    property Delete: TStrings index 3 read FDelete write SetSql;
  end;

[ComponentPlatformsAttribute(pidWin32 or pidWin64)]
  TMyComp = class(TCustomMyComp)
  published
    property Fields;
    property SqlCommands;
  end;

TSqlCommands = class(TCustomSqlCommands)
  published
    property Insert;
    property Update;
    property Delete;
  end;

//------- Fields -----------

  TFields = class(TCollection)
  private
    FOwner: TCustomMyComp;
    function GetItem(Index: Integer): TFieldsItem;
    procedure SetItem(Index: Integer; Value: TFieldsItem);
  protected
    function GetOwner: TPersistent; override;
    procedure Update(Item: TCollectionItem); override;
  public
    constructor Create(AOwner: TCustomMyComp);
    function Add: TFieldsItem;
    function Owner: TCustomMyComp;
  end;

  TFieldsItem = class(TCollectionItem)
  private
    FOwner: TCustomMyComp;
    FSqlCommands: TFieldsSqlCommands;
    procedure SetSqlCommands(Value: TFieldsSqlCommands);
  protected
    function GetDisplayName: String; override;
    procedure SetIndex(Value: Integer);  override;
  public
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    property SqlCommands: TFieldsSqlCommands read FSqlCommands write SetSqlCommands;
  end;

  TFieldsSqlCommands = class(TCustomSqlCommands)
  published
    property Select;
    property Insert;
  end;

我面临两个问题:

  1. 属性SqlCommands: TSqlCommands包含在TCustomSqlCommands下定义的所有属性,即使我定义为仅发布Insert,Update,Delete
  2. 属性Fileds->SqlCommands: TFieldsSqlCommands不包含任何属性,即使我将其定义为只发布Select,Insert

我做错了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-27 16:03:06

  1. 典型的设计模式是让TCustom...类将其属性定义为publicprotected,但从不将其定义为published。这样,派生类就可以根据需要决定要将哪些属性提升到published。这将允许TSqlCommands不发布Select属性,允许TFieldsSqlCommands不发布UpdateDelete属性。
  2. 您的Fields属性是一个TFields对象(BTW,VCL已经在DB单元中有一个TFields类,因此您应该考虑将类重命名为更独特的类)。您的TFields类没有SqlCommands属性,而是TFieldsItem的属性。因此,您需要访问您的字段项之一,才能到达其SqlCommands属性。 但是,尽管TFieldsTFieldsItem对象的集合,但您还没有声明一个属性来公开对TFieldsItem对象指针的直接访问(尽管您已经为该属性声明了getter/setter方法)。您正在从Items[]继承基本TCollection属性,并且该属性公开TCollectionItem对象指针,您必须将这些指针类型转换为TFieldItem。因此,您应该将自己的属性(任意命名)添加到TFields类中,以处理类型转换: TFields = class(TCollection)私有..。函数GetField(索引:整数):TFieldsItem;过程SetField(索引:整数;值: TFieldsItem);公众..。属性FieldsIndex:整数: TFieldsItem读取GetField写入SetField默认值; 顺便说一句,由于TFields有一个Owner,所以您应该考虑从TOwnedCollection而不是直接从TCollection派生它。
票数 2
EN

Stack Overflow用户

发布于 2017-04-27 08:18:52

我们是在讨论代码中的可见性吗?如果是,那么正确的做法是将所有属性视为公共属性,因为发布的属性具有相同的可见性。这两者之间唯一的区别是,已发布的属性包含在RTTI中,因此可以在对象检查器中看到它们。但是在代码中,您可以平等地访问公共属性和已发布的属性。

因此,如果您的第一个问题是从编码方面,这是正确的行为。

关于你的第二个问题:

如果从Fields实例访问TMyCustomComp属性,则不直接具有SqlCommands属性,因为您只能访问从TCollection继承的TFields对象。首先必须访问其中一个项,如果需要将其强制转换为TFieldsItem,则可以访问其SqlCommands属性。

在您的TCustomSqlCommands中,已经发布了这些属性,而在TFieldsSqlCommands中则再次发布了这些属性。我不知道这是否是一个问题,但也许您可以尝试在TCustomSqlCommands中公开它们,并将已发布的内容保存在TFieldsSqlCommands中。但是,由于它们的可见性,您仍然应该能够在代码中访问它们。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43651982

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档