Recent

Author Topic: Create inherited class  (Read 2092 times)

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Create inherited class
« Reply #15 on: May 03, 2022, 02:01:42 pm »
I checked and tested: they were all override. If you change that to virtual, the compiler complains the previous one is hidden, which you can fix by using both virtual and reintroduce. But, as the documentation says:

"Classes have virtual methods, just as objects do. There is however a difference between the two. For objects, it is sufficient to redeclare the same method in a descendent object with the keyword virtual to override it. For classes, the situation is different: virtual methods must be overridden with the override keyword. Failing to do so, will start a new batch of virtual methods, hiding the previous one. The Inherited keyword will not jump to the inherited method, if Virtual was used."

So that won't work. Although that is needed if you change the parameters or return type, it becomes a different function.

So how should it work? What is it I don't understand?


Edit: ah, found it. There was a method with the same name, but a default parameter.
« Last Edit: May 03, 2022, 02:35:08 pm by SymbolicFrank »

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Create inherited class
« Reply #16 on: May 04, 2022, 09:15:28 am »
Edit: ah, found it. There was a method with the same name, but a default parameter.

If you had shown more code we might have been able to help there as well, but good thing that you found it nevertheless. 8)

So that won't work. Although that is needed if you change the parameters or return type, it becomes a different function.

Not quite. There is a small exception, namely covariant return type which is supported by FPC, but not by Delphi. This means that an overridden virtual method can use a narrower return type than the parent method and is still considered equal (cause it still fullfills the “contract” of the parent).

Example:

Code: Pascal  [Select][+][-]
  1. program tvirt;
  2.  
  3. {$mode objfpc}
  4.  
  5. type
  6.   TTest = class
  7.     function Test: TObject; virtual;
  8.   end;
  9.  
  10.   TTestSub = class(TTest)
  11.     function Test: TTest; override;
  12.   end;
  13.  
  14. function TTest.Test: TObject;
  15. begin
  16.   Result := TObject.Create;
  17. end;
  18.  
  19. function TTestSub.Test: TTest;
  20. begin
  21.   Result := TTest.Create;
  22. end;
  23.  
  24. begin
  25.  
  26. end.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Create inherited class
« Reply #17 on: May 04, 2022, 11:31:18 am »
Ok, thanks.

I fixed everything, and I'm now back to the very first implementation: simply overriding everything. Like this:

Code: Pascal  [Select][+][-]
  1.     constructor Create; override; overload;
  2.     constructor Create(ThisName: string); override; overload;
  3.     constructor Create(ThisName: string; ThisValue: Variant); override; overload;
  4.     constructor Create(ThisParent: TSNode); override; overload;
  5.     constructor Create(ThisParent: TSNode; ThisName: string); override; overload;
  6.     constructor Create(ThisParent: TSNode; ThisName: string; ThisValue: Variant);
  7.       override; overload;
  8.     constructor Deserialize(ThisText: string); override;
  9.     function Add: TNode; override; overload;
  10.     function Add(ThisName: string): TNode; override; overload;
  11.     function Add(ThisName: string; ThisValue: Variant): TNode; override; overload;
  12.     function Add(ThisNode: TNode): SizeInt; override; overload;
  13.  

This is just a snippet, there are more. The constructors of the superclasses, which have the constructors of their superclasses (with and without ThisParent). And everything that calls a constructor, just inserting "inherited" doesn't work (that's why they have to be overridden in the first place). Which was what I wanted a better solution for.

The thing is, that with virtual constructors, the right one is called, but it's probably the type you declared in the method:

Code: Pascal  [Select][+][-]
  1. function TNode.Add: TNode;
  2. var
  3.   i: SizeInt;
  4. begin
  5.   Result := nil;
  6.  
  7.   i := MyChildren.Add(TNode.Create); // This is the problem
  8.  
  9.   if i >= 0 then
  10.   begin
  11.     Result := TNode(MyChildren[i]);
  12.     Result.Assign(Self);
  13.     Result.MyParent := Self;
  14.   end;
  15. end;

So it's useless to simply call "inherited".

And I'm feeling pretty stupid at the moment: if you keep on changing these things, after a while you don't get how it is supposed to work anymore.

Anyway, this seems to work:

Code: Pascal  [Select][+][-]
  1.   i := MyChildren.Add(TSNode(Self.ClassType.Create));

(In the superclass.)

At least the instance created is of the right class type, but the initialization is incomplete. I'll try removing all the overloads and see what happens.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Create inherited class
« Reply #18 on: May 17, 2022, 10:25:02 am »
So, now I have a whole class hierarchy (TSerializable -> TSValue -> TSNameValue -> TSNode -> TNode), where, if in doubt, I create new instances with: Self.ClassType.Create. But the whole tree is filled with TNodes, everything else is to reduce code duplication and making sure the right constructor/method is called.

This works, until I start moving nodes around. After a while, when the runtime is determining what to call, TObject.InheritsFrom fails here: "vmt := vmt^.vParent;". It seems it lost track of what kind of object it should be?

I have tried to find what is happening for the last day, but it totally baffles me.

Edit: never mind, I found it: Clear and Assign sometimes overwrote values that broke the chain.
« Last Edit: May 17, 2022, 11:35:08 am by SymbolicFrank »

 

TinyPortal © 2005-2018