- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个基类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() ,则执行基类的代码,这不是我想要的。并且将该方法定义为虚拟也不会完全起作用,因为每个子级别都可能是“最后一个”级别。或不。
我的最终目标是尽可能地概括这一点,因此我不需要将每个类(class)都要求为候选人。也许我在这里遗漏了一些基本的东西,比如 GetRealClass( oThread ).Call( 'Terminate' );
和 GetRealClass( oThread ).Set( 'Stop', TRUE );
将是一个梦想。
我至少能够概括这段代码,这样我只需要编写一次吗?像 FindMethod
之类的对象,我也告诉了它的类类型?
最佳答案
处理这个问题的正确方法是使用虚方法。该机制旨在允许基于对象的运行时类型进行方法分派(dispatch)。换句话说,正是您辛苦的类型检查代码所做的。
但是您正在努力解决这样一个事实:您想要将您的方法命名为 Terminate
,这是一个非虚拟的现有方法的名称。那么,如何克服这个问题。
好吧,如果您决定命名为Terminate
,因为您的方法调用了TThread.Terminate
,然后执行其他任务,那么框架为您提供了一种简单的方法出去。让我们看看TThread.Terminate
的实现。
procedure TThread.Terminate;
begin
if FExternalThread then
raise EThread.CreateRes(@SThreadExternalTerminate);
FTerminated := True;
TerminatedSet;
end;
注意对 TermminateSet
的调用。这是一个虚拟方法,其实现如下:
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
引用,而是持有 TBaseThread
引用。
关于delphi - 调用子类非虚方法或设置子类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35744062/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!