在类TList的属性
property Items[Index: Integer]: Pointer read Get write Put; default;
的写方法中用到了这样一个方法:
procedure TList.Put(Index: Integer; Item: Pointer);
var
Temp: Pointer;
begin
if (Index < 0) or (Index >= FCount) then
Error(@SListIndexError, Index);
if Item <> FList^[Index] then
begin
Temp := FList^[Index];
FList^[Index] := Item;
if Temp <> nil then
Notify(Temp, lnDeleted);
if Item <> nil then
Notify(Item, lnAdded);
end;
end;
上面的Notify来源是类TList的一个方法,
procedure Notify(Ptr: Pointer; Action: TListNotification); virtual;
但实现代码代码里面什么也没做,请问编译器到底隐藏了什么?(查帮助也没有)
property Items[Index: Integer]: Pointer read Get write Put; default;
的写方法中用到了这样一个方法:
procedure TList.Put(Index: Integer; Item: Pointer);
var
Temp: Pointer;
begin
if (Index < 0) or (Index >= FCount) then
Error(@SListIndexError, Index);
if Item <> FList^[Index] then
begin
Temp := FList^[Index];
FList^[Index] := Item;
if Temp <> nil then
Notify(Temp, lnDeleted);
if Item <> nil then
Notify(Item, lnAdded);
end;
end;
上面的Notify来源是类TList的一个方法,
procedure Notify(Ptr: Pointer; Action: TListNotification); virtual;
但实现代码代码里面什么也没做,请问编译器到底隐藏了什么?(查帮助也没有)
解决方案 »
- 如何用DELPHI编写这个界面信息
- 请问大家一 个多线程的问题,(同步或者锁定)
- 用代码在form上添加Label的问题
- 如何把sql資料表用delphi直接匯到*.dbf表中.急在線等待
- 键盘hook的问题,请大虾帮忙!
- 100分求救一个异常的解决,大虾们都进来看看
- 散分!兄弟們進來祝福我的朋友---星星~~第二贴
- 寻求一(小型)医院管理系统的源代码,价格面谈(1000-8000元之间)!
- 急,我的SQL server2000的服务器管理器启动不起来了,怎么办?帮帮我!!
- 请教高手:如何得到鼠标进入和离开一控制件的事件?
- 用过ReportMachine的朋友来看看!
- TreeView的简单问题!!!
好像这样:
var
List:TList;
item:Pointer ;
begin
List:=TList.Create;
List.add(Item);
item:=...
.....
{下面改变FList^[Index]的值}
List.item[index]:=item
{这里就调用了PUT方法}
end;
在Put里先判断下标是否越界,没有的话再看值有没有改变,如有改变,把旧指针取出来放到Temp 中再放入新指针到数组里去,但搞不懂这个Notify做了什么。
procedure TList.Notify(Ptr: Pointer; Action: TListNotification);
begin
//编译器一定是做了一些工作
end;
TCollection.NotifyResponds when items are added to or removed from the collection.type TCollectionNotification = (cnAdded, cnExtracting, cnDeleting);
procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); virtual;DescriptionApplications can抰 call the protected Notify method. It is called automatically when the items in the collection change.Item is the item that was just added to or that is about to be removed from the collection.
TList.Notify确实“什么都没做”,但它并非是“没有用”(不仅又想起了关于TObject.DefaultHandler的那场讨论来了),它是留给你进行override的。
至于具体操作,你可以参看一下TObjectList和TInterfaceList的实现,它们都override了这个方法,以便正确地释放List中的对象/接口。
如果 TList 的后代类在插入或删除一个元素后,需要特殊的处理,则后代类可以实现这个 Notify 方法,在这个方法中进行处理。如果不需要处理,则可以不用实现这个方法。
Notify 纯粹是为了方便后代类。
这样的方法保存在虚方法地址表(VMT)(对象类的虚方法地
址表(VMT – Vritual Method Table)中,
如果你search一下,就会发现此方法广泛存在于Classes类中,但参数不同,不过作用大同小异吧,不过在我看来,
TList.就像一个dbgrid 而TCollection(随便一个)就象stringgrid了
dbgrid没有fixcol属性,但stringgrid有,要想使dbgrid具备fixcol那就要进行强制转换
也就是说假如dbgrid也有fixcol属性,但只是没有具体实现而要让用户通过其后代类进行实现
达到同属于dbgrid但能有不同效果的作用,也就是多态了在要不就是borland为了和别的类相呼应,加了这么个东西,其实完全没用,^_^
但TCollection也有此方法,但有操作,也就是说.......
我们知道,虚方法、抽象方法、接口都能实现多态(是否接口才是真正意义上的、更为广泛的多态);对于类的抽象方法,在类本身没有任何实现,所以也不能创建基于抽象类的实例;虚方法可以有实现,也可以什么都不做(就像上面),具体的实现留给其派生类去处理;对于接口,在接口类里声明的方法需要支持接口的类去实现;
对于上面的问题,其实我最大的疑问还不在这里,我在想,这个类的NOTIFY方法是在TLIST里被调用的即使其派生类覆盖了该方法,那么在TLIST的PUT里能调用到其派生类的方法吗?
后来看了TObjectList,明白了原因所在:
再看一看下面的代码:
procedure TList.Put(Index: Integer; Item: Pointer);
var
Temp: Pointer;
begin
if (Index < 0) or (Index >= FCount) then
Error(@SListIndexError, Index);
if Item <> FList^[Index] then
begin
Temp := FList^[Index];
FList^[Index] := Item;
if Temp <> nil then
Notify(Temp, lnDeleted);
if Item <> nil then
Notify(Item, lnAdded);
end;
end;
如上我们知道对于类方法(或对象方法)来说,其中有隐藏了一个代表对象本身的SELF参数上面的代码实际上是这样的:
procedure TList.Put(Index: Integer; Item: Pointer);
var
Temp: Pointer;
begin
with self do
begin
......
end;
end;
这样的话,当其派生类调用PUT时就是调用的派生类的PUT方法,同样NOTIFY也就是派生类的NOTIFY,所以自然没有问题。
重要的不再于self,而在于Notify是个虚函数,可以被衍生类override,所以才能完成“在基类中调用衍生类的方法”的任务。