4

In this question you see that is possible to create an abstract class adding the abstract keywrod. I am translating a project in Delphi but I see that it allows the creation of an abstract class. This is the code:

type
 TCableSPF = class abstract
  //code
end;

This is an abstract class of course and I have a lot of subclasses that implement it. By the way I see that is it possible to create an instance of this like;

a := TCableSPF.Create;

When I try to call its methods that are virtual and abstract I get the error and this is ok but can I prevent the creation of the class? Or Delphi allows this by default? thanks for the help

Emma Rossignoli
  • 935
  • 7
  • 25
  • 1
    This is a known issue: https://quality.embarcadero.com/browse/RSP-10235 – Sebastian Proske May 28 '17 at 13:28
  • After some Googling, I found an option `{$WARN CONSTRUCTING_ABSTRACT ERROR}`, however, I took a look at [RADStudio's Tokyo documentation](http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Classes_and_Objects) (referenced in the link showed by @SebastianProske), and unfortunately found the following note: "_Delphi allows instantiating a class declared abstract, for backward compatibility, but this feature should not be used anymore_". :-/ – silvioprog Jan 20 '18 at 00:56

1 Answers1

8

The class abstract is a holdover from the Delphi for .Net days.
For reasons unknown there is no (current) implementation behind this keyword.

If you want to prevent instantiation of an abstract class, this keyword will not help. Instead do the following:

type
  TCableSPF = class abstract
  //code
strict protected
  //Define all constructors for an abstract class as protected.
  constructor Create; virtual; reintroduce;
end;

By defining all constructors as protected, only descendent object can access the constructor, other code cannot access the constructor.
Because you reintroducing the virtual constructor, you also cannot instantiate it using:

unit A; 

type
  TMyAbstractObject = class abstract(TObjectX)
  strict protected
    constructor Create; virtual; reintroduce;
  end;

...
unit B;

  TMyClass = class of TObjectX;

  AbstractObjectInstance = TMyClass.Create;  //Will not work for TMyAbstractObject 

Note that you should not declare the constructor override. Instead declare it virtual reintroduce (or just reintroduce if you don't want to allow virtual constructors).

Johan
  • 74,508
  • 24
  • 191
  • 319
  • Thank you very much. That is the same thing that C++ does because it doesn't have the abstract keyword. Btw, I have to use a workaround I see. I hope they will fix this because it is annoying :/ – Emma Rossignoli May 28 '17 at 13:35
  • why should I reintroduce and not override? Is that because the definition that abstract has no implementation? – Emma Rossignoli May 28 '17 at 13:38
  • There was implementation behind it in the .net compiler. – David Heffernan May 28 '17 at 14:26
  • @EmmaRossignoli, declaring it `override` defeats the whole purpose because then you can instantiate a hidden constructor using a class of class constructor (what other languages call a class factory construct) using the virtual nature of the constructor. – Johan May 28 '17 at 14:58
  • But you receive a warning when you try to instantiate a class marked as `abstract`, don't you? If so, then I would stress enough to resolve compiler warnings (have no Delphi by hand to verify right now). – Victoria May 28 '17 at 18:48
  • 1
    Not necessarily, @Victoria. Creating an abstract class via a metaclass variable doesn't cause the compiler to issue a warning. – Rob Kennedy May 29 '17 at 02:18