Ami*_*ack 3 delphi polymorphism
我有一个基类TThread,它有像TThreadSockandTThreadPool这样的子类,它覆盖了该.Terminate()方法。这些孩子的孩子(如TThreadSockDownload或TThreadPoolCollect)继承了这些.Terminate()方法(甚至可能覆盖它们):
type
TThreadSock= class( TThread )
procedure Terminate; // Hides TThread.Terminate
end;
TThreadSockDownload= class( TThreadSock );
TThreadSockUpload= class( TThreadSock )
procedure Terminate; // Hides TThreadSock.Terminate
end;
TThreadPool= class( TThread )
procedure Terminate; // Hides TThread.Terminate
end;
TThreadPoolCollect= class( TThreadPool );
Run Code Online (Sandbox Code Playgroud)
我的问题是:我有一个可以包含所有内容的列表,所以最常见的分母是TThread. 从那个基类我需要调用最“幼稚”的.Terminate()方法。目前我的方法是这样的:
var
oThread: TThread;
begin
oThread:= GetNextThread();
if oThread is TThreadSockDownload then TThreadSockDownload(oThread).Terminate() else
if oThread is TThreadSockUpload then TThreadSockUpload(oThread).Terminate() else
if oThread is TThreadPoolCollect then TThreadPoolCollect(oThread).Terminate() else ...
Run Code Online (Sandbox Code Playgroud)
......你就会知道这会导致什么。没什么好说的,我也必须在其他地方使用这段代码。如果我调用,oThread.Terminate()则执行基类的代码,这不是我想要的。并且将方法定义为virtual也不会完全起作用,因为每个子级别都可能是“最后一个”级别。或不。
我的最终目标是尽可能地概括这一点,所以我不需要要求每个班级都作为候选人。也许我失去了一些东西基本在这里,像GetRealClass( oThread ).Call( 'Terminate' );和GetRealClass( oThread ).Set( 'Stop', TRUE );将是一个梦想。
我至少能够概括这段代码,所以我只需要编写一次吗?像FindMethod在一个对象上我也有告诉它的类类型的东西?
处理这个问题的正确方法是使用虚方法。此机制旨在允许基于对象的运行时类型进行方法调度。换句话说,正是您辛苦的类型检查代码所做的。
但是您正在努力解决您想要命名您的方法的事实Terminate,这是一个非虚拟的现有方法的名称。那么,如何度过难关。
好吧,如果您决定名称Terminate是因为您的方法调用TThread.Terminate,然后执行其他任务,那么该框架为您提供了一个简单的方法。我们来看看 的实现TThread.Terminate。
procedure TThread.Terminate;
begin
if FExternalThread then
raise EThread.CreateRes(@SThreadExternalTerminate);
FTerminated := True;
TerminatedSet;
end;
Run Code Online (Sandbox Code Playgroud)
请注意对 的调用TerminatedSet。那是一个虚方法,它的实现是这样的:
procedure TThread.TerminatedSet;
begin
end;
Run Code Online (Sandbox Code Playgroud)
它什么都不做。提供它是为了允许您在派生类中覆盖它,并在调用非虚拟方法时Terminate调用它。
所以你会这样做:
type
TMyDerivedThread = class(TThread)
protected
procedure TerminatedSet; override;
end;
....
procedure TMyDerivedThread.TerminatedSet;
begin
inherited;
// do your class specific tasks here
end;
Run Code Online (Sandbox Code Playgroud)
然后控制线程的代码可以调用非虚Terminate方法,但仍然调用这个虚方法。
oThread := GetNextThread;
oThread.Terminate;
Run Code Online (Sandbox Code Playgroud)
现在,另一方面,您的Terminate方法可能不会调用TThread.Terminate. 在这种情况下,方法会有所不同。您仍然需要一个虚方法,但如果TThread该类不包含适当的虚方法,则需要引入一个。这意味着派生一个新的基类以引入该虚方法。
type
TBaseThread = class(TThread)
public
procedure MyTerminate; virtual; abstract;
end;
Run Code Online (Sandbox Code Playgroud)
我已经做了这个摘要,但你可能不想。我们无法判断,因为我们不知道您的线程实现是做什么的。你可以决定这个方法是否应该是抽象的。
现在你可以像其他任何方法一样覆盖这个虚拟方法,我相信你已经理解了。您需要进行的另一个更改是,TThread在对线程实例进行操作时,您不持有TBaseThread引用,而是持有引用。
| 归档时间: |
|
| 查看次数: |
403 次 |
| 最近记录: |