我如何确定抽象方法是否已实现?

发布于 2024-12-18 14:58:20 字数 536 浏览 4 评论 0原文

我正在使用一个非常大的delphi第三方库,没有源代码,这个库有几个带有抽象方法的类。我需要确定子孙类在运行时何时实现抽象方法,以避免出现 EAbstractError: Abstract Error 并向用户显示自定义消息或改用另一个类。

例如,在这段代码中,我想在运行时检查 MyAbstractMethod 是否已实现。

type
  TMyBaseClass = class
  public
    procedure MyAbstractMethod; virtual; abstract;
  end;

  TDescendantBase = class(TMyBaseClass)
  public
  end;

  TChild = class(TDescendantBase)
  public
    procedure MyAbstractMethod; override;
  end;

  TChild2 = class(TDescendantBase)
  end;

如何在运行时确定抽象方法是否在后代类中实现?

I'm using a very large delphi third party library without source code, this library has several classes with abstract methods. I need to determine when an abtract method is implemented by a Descendant class in runtime to avoid the EAbstractError: Abstract Error and shows a custom message to the user or use another class instead.

for example in this code I want to check in runtime if the MyAbstractMethod is implemented.

type
  TMyBaseClass = class
  public
    procedure MyAbstractMethod; virtual; abstract;
  end;

  TDescendantBase = class(TMyBaseClass)
  public
  end;

  TChild = class(TDescendantBase)
  public
    procedure MyAbstractMethod; override;
  end;

  TChild2 = class(TDescendantBase)
  end;

How I can determine if an abstract method is implemented in a Descendant class in runtime?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

卸妝后依然美 2024-12-25 14:58:21

您可以使用 Rtti,GetDeclaredMethods 函数获取以下列表在反射(当前)类型中声明的所有方法。因此,您可以检查该方法是否存在于该函数返回的列表中。

function MethodIsImplemented(const AClass:TClass;MethodName : string): Boolean;
var
  m   : TRttiMethod;
begin
  Result := False;
  for m in TRttiContext.Create.GetType(AClass.ClassInfo).GetDeclaredMethods do
  begin
   Result := CompareText(m.Name, MethodName)=0;
   if Result then
    break;
  end;
end;

或者您可以比较 Parent.Name 属性TRttiMethod 并检查是否与当前类名称匹配。

function MethodIsImplemented(const AClass:TClass;MethodName : string): Boolean;
var
  m   : TRttiMethod;
begin
  Result := False;
  m:=TRttiContext.Create.GetType(AClass.ClassInfo).GetMethod(MethodName);
  if m<>nil then
   Result:=CompareText(AClass.ClassName,m.Parent.Name)=0; 
end;

you can use the Rtti, the GetDeclaredMethods function get a list of all the methods that are declared in the reflected (current) type. So you can check if the method is present in the list returned by this function.

function MethodIsImplemented(const AClass:TClass;MethodName : string): Boolean;
var
  m   : TRttiMethod;
begin
  Result := False;
  for m in TRttiContext.Create.GetType(AClass.ClassInfo).GetDeclaredMethods do
  begin
   Result := CompareText(m.Name, MethodName)=0;
   if Result then
    break;
  end;
end;

or you can compare the Parent.Name property of the TRttiMethod and check if match with the current class name.

function MethodIsImplemented(const AClass:TClass;MethodName : string): Boolean;
var
  m   : TRttiMethod;
begin
  Result := False;
  m:=TRttiContext.Create.GetType(AClass.ClassInfo).GetMethod(MethodName);
  if m<>nil then
   Result:=CompareText(AClass.ClassName,m.Parent.Name)=0; 
end;
萧瑟寒风 2024-12-25 14:58:21
function ImplementsAbstractMethod(AObj: TMyBaseClass): Boolean;
type
  TAbstractMethod = procedure of object;
var
  BaseClass: TClass;
  BaseImpl, Impl: TAbstractMethod;
begin
  BaseClass := TMyBaseClass;
  BaseImpl := TMyBaseClass(@BaseClass).MyAbstractMethod;
  Impl := AObj.MyAbstractMethod;
  Result := TMethod(Impl).Code <> TMethod(BaseImpl).Code;
end;
function ImplementsAbstractMethod(AObj: TMyBaseClass): Boolean;
type
  TAbstractMethod = procedure of object;
var
  BaseClass: TClass;
  BaseImpl, Impl: TAbstractMethod;
begin
  BaseClass := TMyBaseClass;
  BaseImpl := TMyBaseClass(@BaseClass).MyAbstractMethod;
  Impl := AObj.MyAbstractMethod;
  Result := TMethod(Impl).Code <> TMethod(BaseImpl).Code;
end;
与君绝 2024-12-25 14:58:21

查看 VCL 源代码(在 Classes.pas 中)中 32 位版本的 TStream.Seek() 方法的实现。它执行检查以确保在调用 Seek() 的 64 位版本之前已被覆盖。它不涉及 TRttiContext 查找来执行此操作,只是通过其父/子 VTable 条目进行简单循环,类似于 Zoë 的答案所示。

Look at the implementation of the 32-bit version of the TStream.Seek() method in the VCL source code (in Classes.pas). It performs a check to make sure the 64-bit version of Seek() has been overridden before calling it. It doesn't involve TRttiContext lookups to do that, just a simple loop through its Parent/Child VTable entries, similar to how Zoë's answer shows.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文