将对象数据字段复制到子类实例中

时间:2014-05-28 07:34:48

标签: delphi object subclassing

我有两个班,TNode和TMaster。我从TNode继承了TMaster。

目标是创建一个包含先前创建的TNode实例的所有数据的TMaster实例。有没有“内置”方法来实现这一点,还是应该手动完成?

type

  Tnode = class(TObject)
  private
    FSite: TSite;
    FhndNode: THandle; 
    FnodeID: word;
    FslaveID: longword; 
    FcoordX: double; 
    FcoordY: double;     
    FhndSubRect: THandle; 
    FdNodes: TdNodes; 
    Fdestinations: Tdestinations;
    FGroup: byte;
    FDomain: byte;
    FRFsense: byte; 
    FComm: byte; 
    FlcIDtextHnd: THandle; 
    ...
  public
    constructor create();
    ...
  end;

  TMaster = class(TNode);
  private
    FName: string;
    FIP: string; 
    FMAC: string;
  public
    constructor create( aHandle: HWND; aName, aIP, aMAC: string );
    procedure MSG_SETCONFIG( aNode: TNode; aSwitch: integer ); 
    property Name: string read FName write FName;
    property IP: string read FIP write FIP;
    property MAC: string read FMAC write FMAC;
  end;

2 个答案:

答案 0 :(得分:3)

如果我理解你正在尝试的是实现数据可重用性。这不能通过类继承来解决。

类继承的作用是让你创建包含父类所有功能的类(不需要复制父类的整个代码),然后通过在这个新类中引入新功能来进一步扩展该功能。创建此类时,将创建父类和子类的所有字段。

为了达到你想要的效果,你应该使用两个单独的类,你需要独立创建它们。 第一类应包含所有最终类共有的数据。 第二类包含aditional数据,并使用属性简单地转发第一类数据,因此最终它似乎包含来自两个类的数据。 为了做到这一点,你的第二堂课应该引用存储在其中的第一堂课。 让我给你看一下代码示例:

type
  TCommonData = class(TObject)
  private
    FSomeData: Integer;
  protected
    procedure SetSomeData(AValue: Integer);
  public
    property SomeData: Integer read FSomeData write SetSomeData;
  end;

  TExtendedData = class(TObject);
  private
    FMoreData: Integer;
    //Common data
    FCommonData: TCommonData;
  protected
    procedure SetMoreData(AValue: Integer);
    //Common data
    procedure SetCommonData(AValue: TCommonData);
    function GetSomeData: Integer;
    procedure SetSomeData(AValue: Integer);
  public
    constructor Create(ACommonData: TCommonData);
    property MoreData: Integer read FMoreData write SetMoreData;
    //External data
    property CommonData: TCommonData read FCommonData write SetCommonData;
    property SomeData: Integer read GetSomeData write SetSomeData;
  end;

implementation

TCommonData.SetSomeData(AValue: Integer);
begin
  FSomeData := AValue;
end;

TExtendedData.Create(ACommonData: TCommonData);
begin
  //Assign external connection to common data object
  FCommonData := ACommonData;
end;

TExtendedData.SetMoreData(AValue: Integer);
begin
  FMoreData := AValue;
end;

TExtendedData.SetCommonData(AValue: TCommonData);
begin
  FCommonData := AValue;
end;

TExtendedData.GetSomeData: Integer;
begin
  //Check to see if external class conection has been assigned
  if FCommonData <> nil then
  begin
    result := FCommonData.SomeData;
  end
  //Set some uniqe result if no external connection has been assigned
  else result := -1; 
end;

TExtendeddata.SetSomedata(AValue: Integer);
begin
  //Check to see if external class conection has been assigned
  if FCommonData <> nil then
  begin
    FCommonData.SomeData := AValue;
  end
  else //Log error or raise Exception here
end;

现在,您可以访问这两个类中的所有数据,就好像它将存储在一个类中一样。

注意:使用此方法时,您需要注意某些事项:

应始终在转发其数据的其他类之前创建TCommonData类。它也应该在最后销毁。

如果您在其他类中更改TCommonData数据,就像在我的代码示例中那样,并且您正在使用多线程,则应该处理线程同步以避免数据损坏。最简单的方法是在TCommonData SetSomeData过程中添加一个crictical异常。

所有类应始终通过其属性从TCommonData读取或写入数据,而不是直接访问其字段,以使上面提到的线程同步方法起作用。

从未在后续课程中使用

property Somedata: Integer read FCommonData:SomeData write FCommonData.SomeData;

始终使用getter / setter方法,以便添加aditional检查以避免在将外部连接分配给公共数据类之前尝试访问公共数据时可能发生的访问冲突。

答案 1 :(得分:2)

应该手动完成。

您可能希望为Assign后代实现TPersistent之类的内容。为了使它工作,你必须覆盖Assign(To)例程,实现深度逐字段复制。