Delphi - 必须的一致.
大家好,我是HuangJacky,技术交流.
这个是在工作发现的一个问题,而且是很久的问题了.当时已经写成文章了.但是(往往时常都有这个但是)系统挂了,文章还没有发出来.
好,赶紧发出来.
首先还原下问题:(这个 插件居然没有Pascal)
1: //首先定义具有继承关系的接口
2: IBase = interface
3: procedure TalkBase;
4: end;
5:
6: IDerive = interface(IBase)
7: procedure TalkDerive;
8: end;
9: //实现的类
10: TBase = class(TInterfacedObject, IBase)
11: procedure TalkBase;
12: end;
13:
14: TDerive = class(TBase, IDerive)
15: private
16: FTest: Integer;
17: public
18: constructor Create();
19: procedure TalkBase;
20: procedure TalkDerive;
21: end;
类得实现.
1: { TDerive }
2:
3: constructor TDerive.Create;
4: begin
5: FTest:= 55;
6: end;
7:
8: procedure TDerive.TalkBase;
9: begin
10: ShowMessage('Derive say base');
11: end;
12:
13: procedure TDerive.TalkDerive;
14: begin
15: ShowMessage('Derive');
16: end;
17:
18: { TBase }
19:
20: procedure TBase.TalkBase;
21: begin
22: ShowMessage('Base');
23: end;
现在我们有一个列表,列表里面可以装这些接口的:
1: procedure TForm2.Add(Obj: IBase);
2: begin
3: FList.Add(Pointer(Obj))
4: end;
是吧,这样列表里面都是放的接口.我们来看看使用的代码:
1: procedure TForm2.btnTestClick(Sender: TObject);
2: begin
3: //加两个
4: A:= TDerive.Create;
5: Add(A);
6: A:= TDerive.Create;
7: Add(A);
8: //使用
9: A:= TDerive(FList[0]);
10: ShowMessage(IntToStr(A.FTest));//我们预期是55
11: end;
可是结果是怎么样的呢?
为什么是这么多呢?
后来我发现我们加进去的是接口IBase而我们使用的时候是直接转化TDerive.中间少了一步转换pointer->IBase.好的代码改一下:
1: //使用
2: A:= TDerive(IBase(FList[0]));
3: ShowMessage(IntToStr(A.FTest));//我们预期是55
结果: .正确了.
这里说明了什么?TList里面我们加进去的是什么,使用的时候就要先转换成加进去时候的类型后才能再转换成其他类型.
原因呢?
这个是因为Delphi中对象的内存组织决定的.
这个我明天说.现在得睡觉了