-1

I have a Base Class that needs a Prameter like Filename. This Parameter is needed for the Create Call of the TMemIniFile Class.

Whats the correct Way to call the Class function of the current Classtype inside the Base Class Constructor?

TBaseClassClass = Class of TBaseClass;

TBaseClass = class(TMemIniFile)
protected
  class function FileName: string; virtual; abstract;
public
  // Current Solution
  constructor Create(ClassToCreate: TBaseClassClass); reintroduce;
  // wanted Solution
  constructor Create; reintroduce;
end;

TImplementation = Class(TBaseClass)
protected
  class function FileName: string; override;
end;

// Current Solution
constructor TBaseClass.Create(ClassToCreate: TBaseClassClass);
begin
  inherited Create(ClassToCreate.FileName, Encoding.UTF8);
end;
// Wanted Solution
constructor TBaseClass.Create;
begin
  inherited Create(FileName, Encoding.UTF8); // This call to FileName has a Abstract Error because its calling Filename from TBaseClass. But how to solve this elegant?
end;

//Trying to Clarify: Usage:
myWorkingIniFile: TImplementation.Create;  //Filename is defined in Class and the FileName value is used in the Constructor ...  

Can i somehow "dynamically" Typecast inside the Constructor? I have seen the use of RTTI with a call of the function name. But i think there should be another Way. Or am i doing it fundamentally wrong?

  • Looking at your code I have no clue of what you are trying to achieve. So can you please try to explain what you are trying to achieve. What is the purpose of your FileName function in the first place. – SilverWarior Aug 12 '21 at 16:35
  • A shot in the dark: [Calling child class non-virtual method or setting child class property](https://stackoverflow.com/q/35744062/4299358) – AmigoJack Aug 12 '21 at 16:40
  • 2
    Why don't you just pass the filename to the base constructor? – Olivier Aug 12 '21 at 17:52
  • @Olivier its not just one Information and iam trying to have the information only once defined. But you have hinted me in the Right direction. – Quelltextknecht Aug 13 '21 at 09:40
  • @AmigoJack not quite but together with Olivier i came up with a potential solution. – Quelltextknecht Aug 13 '21 at 09:41

2 Answers2

0

You should never create an instance of a class containing abstract methods. In your example, you should only create instances of TImplementation, never TBaseClass. And if you want the class to be dynamic :

procedure Foo;
var
  vMyClass : TBaseClassClass;
begin
  vMyClass := TImplementation; //or vMyClass := GetSomeClass();
  FMyField := vMyClass.Create;
end;

In this case, you would normally want the constructor of TBaseClass to be virtual.

if you are calling TBaseClass.Create(TImplementation), you are right, that's fundamentally wrong

Ken Bourassa
  • 6,363
  • 1
  • 19
  • 28
  • Sorry, thats not what iam looking for. The Base Class needs Information which i wanted to place in "must override" functions for derived classes. But i can not call those "must override" functions inside the Base Constructor where i need this information becaus the calss itself does not exist at that ime. So i went for class functions. – Quelltextknecht Aug 13 '21 at 09:38
  • @Quelltextknecht I don't believe you fully understand how polymorphism work. Yes you CAN call a `virtual; abstract` method in the constructor of your base class. What you CANNOT (or at least, definitely shouldn't) do is create an instance of a class containing abstract methods. And honestly, the way you want to use the function, it doesn't matter whether it is a class function or a simple method. Both would work. – Ken Bourassa Aug 13 '21 at 13:00
-1

Oh yes thanks for the Comments. (German saying: i did not see the forest for all the trees; something like i did not see the obvious) I came up with something like this:

TBaseClass = class(TMemIniFile)
protected
  class function FileName: string; virtual; abstract;
end;

TImplementation = Class(TBaseClass)
protected
  class function FileName: string; override;
public
  constructor Create; reintroduce;
end;

constructor TImplementation.Create;
begin
  inherited Create(Filename, Encoding);
end;

Additional i now use AfterConstruction for all the other Settings and Setup. no need to use class functions.

  • That code should be in the base class, not in the implementation class. Either that, or there is no point in having a "Filename" function in the base class. – Ken Bourassa Aug 16 '21 at 12:53
  • @KenBourassa i use it as a "Must Override" definition. When you create a class and not all Virtual abstract functions are declared you get a hint. I Use it to control if someone using it has defined all necessary Functions. (You can even Set this Hint to act as an error) – Quelltextknecht Aug 17 '21 at 17:34
  • Unless you use it elsewhere, having Filename in base class is pointless. you could just as well have `inherited Create('MyFileName', Encoding);` and it would work just fine. And if you wanted descendant of `TImplementation` to use a different filename , you should declare `FileName` in `TImplemention`, not in `TBaseClass`. But the fact is, with the information you supply, I have to conclude the proper location to implement `inherited Create(Filename, Encoding);` is in the constructor of `TBaseClass`. – Ken Bourassa Aug 17 '21 at 18:20