18

I am using a component suite which has many abstract classes. Now I want to apply polymorphism but I am getting Error Abstract Class when I create my object.

Should I override all methods which are virtual even if I don't need it? Are there any workaround or solution?

Fabrizio
  • 7,603
  • 6
  • 44
  • 104
marcostT
  • 573
  • 1
  • 10
  • 20
  • Do you get "Error Abstract Class" at run time or compile time? Compile time should give E2402: Constructing instance of abstract class '%s' – Gerry Coll Jun 01 '11 at 03:04

4 Answers4

29

In order to make an instance of a class, you need to override all methods that are declared as virtual abstract. Even if you don't use them.

If you really want a work around, you can use empty methods. But I won't recommend that.

And to add some more information on the subject:

A method is abstract if it is declared with virtual abstract:

procedure MyMethod(const AMyParameter: Integer); virtual; abstract;

Trivia: You can even override a method as abstract:

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

You need to override these methods in order to instantiate from that class.

And you can declare an entire class as abstract:

type
  TMyClass = class abstract (TMyAncestor)
  end;

You get a warning if you try to instantiate that class.

The counterpart is a sealed class:

type
  TMyClass = class sealed (TMyAncestor)
  end;

You get a warning if you try to inherit from that class.

You can also seal methods, but you need the keyword final for that.

procedure MyMethod(const AMyParameter: Integer); override; final;
Toon Krijthe
  • 52,876
  • 38
  • 145
  • 202
  • 8
    I think you don't have to implement all abstract methods given that you don't call them. It just gives you a compiler warning. If called at runtime an `EAbstractError` is raised. – jpfollenius May 31 '11 at 12:38
  • 3
    I think you need to check the facts stated in this answer – David Heffernan May 31 '11 at 14:51
  • Note that you will only get a warning if you try to implement them directly using the abstract class name, e.g. `Obj := TAbstractObject.Create;`. If you use 'class of' variables or methods that return a class type it is possible to get abstract errors without a compile time warning. e.g. `TAbstractClass = class of TAbstractObject; function GetClass: TAbstractClass; ... Obj := GetClass.Create; // <-- boom` – Gerry Coll Jun 01 '11 at 02:40
  • "Even if you don't use them" - meh.... I don't know about this.! So, you have a parent class (T0) that has a T0.LockDoor() abstract method. And you have 9 child classes that implement the abstract method of the parent. But the 10th class is a bit special and does not need to implement it. It has a StartEngine() method instead ... [to be continued ...] – Gabriel Jun 13 '21 at 09:22
  • [Continuation] ....... So, you implement T10.LockDoor as an empty method and then you call it in your program (by accident) thinking that your door is locked. I personally would let this method unimplemented in T10. If it is called by accident, you will get an EAbstract error during your testing, and you will know that T10.LockDoor was called instead of T10.StartEngine. – Gabriel Jun 13 '21 at 09:22
8

Delphi doesn't have abstract classes as such, only abstract methods. You will get an abstract method exception raised if you call an abstract method.

Put simply you must not call abstract methods. The compiler emits a warming if it detects you instantiating a class with abstract methods. Good practise is to ask the compiler to turn these warnings into errors.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • `Good practise is to ask the compiler to turn these warnings into errors.` and how do we do this? – Johan May 31 '11 at 11:49
  • 5
    @David, not exactly, you can create an abstract class (even without abstract methods) using the TMyClass = class abstract (TMyParent)... – Toon Krijthe May 31 '11 at 11:52
  • 2
    @johan project options, hints and warnings, any warming can be converted into an error – David Heffernan May 31 '11 at 12:45
  • @David, way cool didn't know that you could upgrade your warnings. – Johan May 31 '11 at 12:59
  • 1
    "Good practise is to ask the compiler to turn these warnings into errors." Good practice - true. IMO better practice is to use interfaces instead, which force you to implement them if used. – Vector Jun 01 '11 at 01:28
  • Bringing the answer up to date: nowadays, a class can be marked as "abstract": http://docwiki.embarcadero.com/RADStudio/Sydney/en/Classes_and_Objects_(Delphi) – Gabriel Jun 13 '21 at 09:52
  • 2
    @Z80 I don't think that marking a class as abstract does very much. Isn't it a hangover from the .net days. – David Heffernan Jun 13 '21 at 14:20
  • @DavidHeffernan - Tested. You are right. You can instantiate the class and call its methods. The compiler won't cry hints or warnings. – Gabriel Dec 02 '21 at 09:28
  • From Delphi help: "Note: Delphi allows instantiating a class declared abstract, for backward compatibility, but this feature should not be used anymore". What do they mean by "this feature"? The "abstract" or the instantiation? I guess is the second one. – Gabriel Jun 03 '22 at 14:05
  • @ServerOverflow it relates to the discontinued delphi .net compiler which needed to support classes declared abstract. – David Heffernan Jun 03 '22 at 16:27
2

Your descendant class is still abstract if

  1. it's declared abstract, or
  2. it has at least one method declared abstract, or
  3. it doesn't override and implement all abstract methods from its ancestors
Ondrej Kelle
  • 36,941
  • 2
  • 65
  • 128
  • 2
    Yeah - I've found that it's easier to only abstract those methods that will always have to be overridden. All the other stuff gets 'empty' virtual methods. That said, why is TThread.execute not abstract? – Martin James May 31 '11 at 11:59
  • 1
    @Martin James: You are right, it should actually be abstract, but imagine it were and somebody instantiated a TThread descendant and forgot to override Execute: An EAbstractError would be raised in a background thread and would not be handled, so nobody would realize what happened. It's not easy to find this kind of error. – dummzeuch May 31 '11 at 20:09
  • @ondrej - Checks comments in the answer above. Marking the whole class as abstract does nothing. – Gabriel Dec 02 '21 at 09:32
0

It will produce an error if you override the abstract constructor as it automatically puts inherited into the new constructor which of course is calling the abstract constructor if you use the code auto complete.

e.g.

type
  TMyclass = class (TObject)
  public
    constructor Create(AOwner : TComponent); dynamic; abstract;
  end;

  TMyclass2 = class(TMyclass)
  public
    Constructor Create(AOwner : TComponent); override;
  end;

implementation

constructor TMyclass2.Create(AOwner: TComponent);
begin
  inherited;

end;
Alberto Miola
  • 4,643
  • 8
  • 35
  • 49