Delphi中的抽象类

Delphi中的抽象类,delphi,abstract,delphi-2009,Delphi,Abstract,Delphi 2009,我使用的组件套件有许多抽象类。现在我想应用多态性,但我在创建对象时得到了错误的抽象类 我是否应该覆盖所有虚拟方法,即使我不需要它?有什么解决方法吗?Delphi没有抽象类,只有抽象方法。如果调用抽象方法,将引发抽象方法异常 简单地说,您不能调用抽象方法。如果编译器检测到您使用抽象方法实例化一个类,它将发出警告。好的做法是要求编译器将这些警告转化为错误。如果 它被声明为摘要,或 它至少有一个声明为抽象的方法,或者 它不会覆盖和实现来自其祖先的所有抽象方法 为了创建类的实例,您需要重写所有声明为虚拟

我使用的组件套件有许多抽象类。现在我想应用多态性,但我在创建对象时得到了错误的抽象类


我是否应该覆盖所有虚拟方法,即使我不需要它?有什么解决方法吗?

Delphi没有抽象类,只有抽象方法。如果调用抽象方法,将引发抽象方法异常


简单地说,您不能调用抽象方法。如果编译器检测到您使用抽象方法实例化一个类,它将发出警告。好的做法是要求编译器将这些警告转化为错误。

如果

  • 它被声明为
    摘要
    ,或
  • 它至少有一个声明为抽象的方法,或者
  • 它不会覆盖和实现来自其祖先的所有抽象方法

  • 为了创建类的实例,您需要重写所有声明为虚拟抽象的方法。即使你不使用它们

    如果你真的想要一个变通方法,你可以使用空方法。但我不建议这样做

    并添加有关该主题的更多信息:

    如果使用虚拟抽象声明方法,则该方法是抽象的:

    procedure MyMethod(const AMyParameter: Integer); virtual; abstract;
    
    procedure MyMethod(const AMyParameter: Integer); override; abstract;
    
    type
      TMyClass = class abstract (TMyAncestor)
      end;
    
    琐事:您甚至可以将方法重写为抽象:

    procedure MyMethod(const AMyParameter: Integer); virtual; abstract;
    
    procedure MyMethod(const AMyParameter: Integer); override; abstract;
    
    type
      TMyClass = class abstract (TMyAncestor)
      end;
    
    为了从该类实例化,您需要重写这些方法

    您可以将整个类声明为抽象类:

    procedure MyMethod(const AMyParameter: Integer); virtual; abstract;
    
    procedure MyMethod(const AMyParameter: Integer); override; abstract;
    
    type
      TMyClass = class abstract (TMyAncestor)
      end;
    
    如果尝试实例化该类,将收到警告

    对应的是一个密封类:

    type
      TMyClass = class sealed (TMyAncestor)
      end;
    
    如果尝试从该类继承,将收到警告

    您也可以密封方法,但需要关键字final

    procedure MyMethod(const AMyParameter: Integer); override; final;
    

    如果您重写抽象构造函数,它会产生一个错误,因为它会自动将继承的内容放入新构造函数中。如果您使用代码自动完成,新构造函数当然会调用抽象构造函数

    e、 g


    好的做法是要求编译器将这些警告转化为错误。
    我们如何做到这一点?@David,不完全是这样,您可以使用TMyClass=class abstract(TMyParent)…创建一个抽象类。@johan项目选项、提示和警告,任何升温都可以转化为error@David,way cool不知道可以升级警告。“好的做法是让编译器将这些警告转化为错误。”好的做法-正确。在我看来,更好的做法是使用接口,这会迫使你在使用时实现它们。是的,我发现只抽象那些总是需要重写的方法更容易。所有其他东西都会得到“空”虚拟方法。也就是说,为什么TThread.execute不是抽象的@马丁·詹姆斯:你是对的,它实际上应该是抽象的,但想象一下,它是抽象的,有人实例化了一个TThread子代,却忘了重写Execute:一个EAbstractError会在后台线程中引发,不会被处理,所以没有人会意识到发生了什么。发现这种错误并不容易,我认为你不必实现所有的抽象方法,只要你不调用它们。它只是给你一个编译器警告。如果在运行时调用,将引发
    eabstracteror
    。我认为您需要检查此回答中陈述的事实注意,只有在您尝试直接使用抽象类名实现它们时,才会收到警告,例如
    Obj:=TAbstractObject.Create。如果使用“类的”变量或返回类类型的方法,则可能在没有编译时警告的情况下获得抽象错误。e、 g.
    TAbstractClass=TAbstractObject的类;函数GetClass:TAbstractClass。。。Obj:=GetClass.Create;//“即使你不使用它们”-嗯。。。。我不知道这件事。!因此,您有一个父类(T0),它有一个T0.LockDoor()抽象方法。有9个子类实现父类的抽象方法。但是第10个类有点特殊,不需要实现它。它有一个StartEngine()方法来代替。。。[待续…][续]。。。。。。。因此,您将T10.LockDoor实现为空方法,然后在程序中调用它(意外地)认为您的门已锁定。我个人会让这个方法在T10中没有实现。如果它是意外调用的,您将在测试期间得到一个EAbstract错误,并且您将知道调用了T10.LockDoor而不是T10.StartEngine。您是在运行时还是在编译时得到“错误抽象类”?编译时应给出E2402:构造抽象类“%s”的实例