有一定难度:如何修改(替换)类的只读属性?(100分)

  • 主题发起人 主题发起人 dejoy
  • 开始时间 开始时间
D

dejoy

Unregistered / Unconfirmed
GUEST, unregistred user!
有一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,请教各位!
 
TMyControlEx既是从TMyControl继承,何不将TMyControl的属性FItems设为protected型?
这样FItems对外部是只读的,而对子类TMyControlEx是可见的,在TMyControlEx中可以
直接修改FItems。
 
兄弟,问题的关键就是TItems所在的单元是不能更改的,不然我直接改源代码得了,何必如此费心呢,我想知道的是不改变TItems所在单元代码的实现方法
 
先定义一个参考类:
TMyControlRef = class(TComponent)
private
FItems: TItems;
end;

然后:
constructor TMyControlEx.Create(AOwner: TComponent);
var
litem : TItems;
begin
inherited;
litem := Items;
litem.Free;

litem := TItemsEx.Create(Self);
TMyControlRef(Self).FItems:=litem;
end;
 
这个问题有点难度
不过不是不可以解的
看这段
property Items: TItems read FItems ;
在实例中引用Items时就直接引了TItems 类型的实例
也就是说地址找到了
还有什么不能做的呢
function Test():TItems;
var
it:TItems;
begin
it:=SElf.Items
//然后it就可以写了
Result:=it;
end;

end;
 
声明为 保护型的,子类就可以使用了。
 
大家的方法行不行,在不更改Unit1中任何代码,而unit2中的可以随便改
只要下面的测试通过就说明成功

procedure TForm1.Button1Click(Sender: TObject);
var
ab: TMyControl;
begin
AB := TMyControlEx.Create(nil);
ShowMessage(ab.Items.ClassName); //这里返回 TItemsEx
end;
 
经过测试,Mike1234567890,和Shuzi, 的方法都行不通
 
找到答案了,要解决这个问题,只有用江湖中最厉害最诡异的招式 : 乾坤大挪移~~~~~~
constructor TMyControlEx.Create(AOwner: TComponent);
begin
inherited;
Items.Free;
PPointer(@Items)^ := TItemsEx.Create(Self);
end;
 
》》》经过测试,Mike1234567890,和Shuzi, 的方法都行不通
不可能行不通,我们经常用这种方法。
 
上面兩位的方法和你的是同一個道理啊,他們的還更有效率,因為你釋放了原來的,如果原來的被初始化,你的自己建的就的不到初始化值了
 
>> 那必要要释放原来的,不然怎么把原来的替换成自己的?
 
用周爱民的绝招,通过offset找到私有变量,然后强制转换为你要的类型,就可以直接改了.
具体可以看周的文章.
 
>>不可能行不通,我们经常用这种方法。
真的行不通
我把源程序打包上传了,到下面下载,
http://pickup.mofile.com/7077054618124272
提取码:
7077054618124272
 
回 dinglj1760兄 ,那有周爱民的文章?
 
http://www.delphibbs.com/delphibbs/dispq.asp?lid=892583
如何跨单元、跨类地访问Delphi类的私有域
 
后退
顶部