有一unit1定义如下:
type  TItems = class(TComponent)
  public
  end;  TMyControl = class(TComponent)
  private
    FItems: TItems;
  public
    constructor Create(AOwner: TComponent); override;
    property Items: TItems read FItems ;
  end;implementation{ TMyControl }constructor TMyControl.Create(AOwner: TComponent);
begin
  inherited;
  FItems := TItems.Create(Self);
end;end.另一个Unit2定义如下,从unit中的类继承:
type  TItemsEx = class(TItems)
  private
    FStr: string;
  public
    property Str: string read FStr  write FStr;
  end;  TMyControlEx = class(TMyControl)
  public
    constructor Create(AOwner: TComponent); override;
  end;implementation
{ TMyControlEx }constructor TMyControlEx.Create(AOwner: TComponent);
var
  litem : TItems;
begin
  inherited;
  litem := Items;
  litem.Free;  litem := TItemsEx.Create(Self);
end;我想在不修改unit1的前提下(不能修改),继承它的类,把其中一个属性Items扩展替换为我自己的类TItemsEx,但用上面的方法不行,原来的Items成为nil了,litem成了一个临时变量,并没有替换为Items,请教各位!

解决方案 »

  1.   

    property Items: TItems read FItems write Fitmes;把它公布出来
    unit Unit2;interface
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;type  TItems = class(TComponent)
      public
      end;  TMyControl = class(TComponent)
      private
        FItems: TItems;
      public
        constructor Create(AOwner: TComponent); override;
        property Items: TItems read FItems ;
      end;
      TItemsEx = class(TItems)
      private
        FStr: string;
      public
        property Str: string read FStr  write FStr;
      end;  TMyControlEx = class(TMyControl)
      public
        constructor Create(AOwner: TComponent);override;
      published
        property Items: TItems read FItems write FItems;
      end;
      implementation{ TMyControl }constructor TMyControl.Create(AOwner: TComponent);
    begin
      inherited;
      FItems := TItems.Create(Self);
    end;
    constructor TMyControlEx.Create(AOwner: TComponent);
    var
      litem : TItems;
    begin
      inherited;
      litem := Items;
      litem.Free;  litem := TItemsEx.Create(Self);
    end;end.
      

  2.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      ab: TMyControl;
    begin
      AB :=  TMyControlEx.Create(nil);
      ShowMessage(ab.Items.ClassName)
    end;调用的例子
      

  3.   

    To Top  
     yq3woaini(哈哈镜 http://shop33546080.taobao.com(选择好心情!) ( TItems的定义和我自己的TItemsEx不是在同一unit中的,所以不能使用你的方法,并且TMyControl里是published
        property Items: TItems read FItems write SetItems;
    并且SetItems是这样定义的:
    procedure TMyControl.SetItems(const Value: TItems);
    begin
      FItems.Assign(Value);
    end;而不是property Items: TItems read FItems write FItems;
      

  4.   

    //这个问题,只能用传说中的移魂大法了
    constructor TMyControlEx.Create(AOwner: TComponent);
    begin
      inherited;
      Items.Free;
      PPointer(@Items)^ := TItemsEx.Create(Self);
    end;
      

  5.   

    这招江湖中传说的 移魂大法果然 厉害,我本来的想法也是想用这招,只是功力不到,弄个半殘(Bug不断)~~~
      

  6.   

    直接在继承的类中发布相同名字属性并实现,然后就可以达到Reintroduce的效果了,但这样的话,
    如果用基类调用的话,还是调用基类的那个属性,用起来有局限性,不知道能不能满足你的要求
    ==============
    另外一种方法是,在父类的构造函数中指定实现Item属性的类,
    Constructor Create(AOwner: tComponent; ImpClass: TClass); Reintroduce;
    begin
       FItems:= ImpClass.Create;
       ...........
    end;在继承类中以新的TItemEx来放在ImpClass的位置.
    这种方法在Delphi的接口技术中很常用的,效果也不错
    ===========================================
    取舍自己看着办吧,
      

  7.   

    重新发布属性的方法行不通,因为基类中调用的Items还是TItem,而不是我的TItemEx第二种方法从设计上来说是一个好方法,但由于基类已经设计好,是不能更改,TItems 的构造方法就是Constructor Create(AOwner: tComponent; ImpClass: TClass);这样的,TItems 因为是一个TCollection的儿子,但这个TItems只是TMyControl的一个属性,是在基类里已经建立,不能在TMyControlEx中再指定ImpClass.因为我的前提是不更改基类的代码下实现此功能,所以应该是移魂大法最为合适,应该也是唯一的方法(不知道还有没有另的方法~)