我有一个基类TThread
,它有TThreadSock
和TThreadPool
等子类,它们会覆盖.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 );
我的问题是:我有一个可以包含所有内容的列表,因此最常见的分母是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 ...
...你知道这会导致什么。不用说我必须在其他地方使用这个代码。如果我调用oThread.Terminate()
,则会执行基类的代码,这不是我想要的。将方法定义为virtual
也不会完全奏效,因为每个孩子级别都可能是最后一个"一。或不。
我的最终目标是尽可能地概括这一点,所以我不需要要求每个班级作为候选人。也许我在这里遗漏了一些基本的东西,比如GetRealClass( oThread ).Call( 'Terminate' );
和GetRealClass( oThread ).Set( 'Stop', TRUE );
会是一个梦想。
我至少能够推广这段代码所以我只需要写一次吗?像对象FindMethod
这样的东西我也告诉它的类类型为?
答案 0 :(得分:4)
处理此问题的正确方法是使用虚拟方法。此机制旨在允许基于对象的运行时类型进行方法分派。换句话说,正是您的劳动类型检查代码确实如此。
但是你正在努力解决你想要命名方法Configuration
的事实,这是一个非虚拟的现有方法的名称。那么,如何超越它。
好吧,如果您决定使用名称Terminate
,因为您的方法调用Terminate
,然后执行其他任务,那么框架会为您提供一个简单的方法。让我们看一下TThread.Terminate
的实现。
TThread.Terminate
请注意对procedure TThread.Terminate;
begin
if FExternalThread then
raise EThread.CreateRes(@SThreadExternalTerminate);
FTerminated := True;
TerminatedSet;
end;
的通话。这是一个虚拟方法,其实现如下:
TerminatedSet
它什么都不做。它被允许您在派生类中覆盖它,并在调用非虚方法procedure TThread.TerminatedSet;
begin
end;
时调用它。
所以你会这样做:
Terminate
然后控制线程的代码可以调用非虚拟type
TMyDerivedThread = class(TThread)
protected
procedure TerminatedSet; override;
end;
....
procedure TMyDerivedThread.TerminatedSet;
begin
inherited;
// do your class specific tasks here
end;
方法,但仍然会调用此虚方法。
Terminate
另一方面,现在,oThread := GetNextThread;
oThread.Terminate;
方法不会调用Terminate
,这似乎是合理的。在这种情况下,方法会有所不同。您仍然需要一个虚方法,但如果TThread.Terminate
类不包含适当的虚拟方法,则需要引入一个。这意味着导出一个新的基类以引入该虚方法。
TThread
我已经做了这个摘要,但你可能不想这样做。我们无法告诉,因为我们不知道您的线程实现是做什么的。您可以决定此方法是否应该是抽象的。
现在你可以像任何其他方式一样覆盖这个虚拟方法,这是我相信你已经理解的。您需要做的另一个更改是,在操作线程实例时,不要保留type
TBaseThread = class(TThread)
public
procedure MyTerminate; virtual; abstract;
end;
引用,而是保留TThread
引用。