[fpc-devel] Modifiers...

Sven Barth pascaldragon at googlemail.com
Thu Feb 1 21:14:13 CET 2024


Am 29.01.2024 um 21:56 schrieb Michael Van Canneyt via fpc-devel:
> I didn't say I cannot think of a legitimate use. I said it does not make
> sense to me, as in
>
> "I don't understand what people try to accomplish with this modifier".
>
> Unfortunately I still don't understand after your explanation what 
> adding 'final' is supposed to accomplish. It may well be legitimate, 
> but I have currently no opinion as I don't understand it.
>
> Maybe an actual code example would be more enlightening.
>
> That way I can also add it to the docs once I understand the intended 
> use myself.

It took me a while to find a suitable example, but now I've got one 
that's sounds useful.

Assume you have a class TCleanup that deals with cleaning up some stuff 
with a virtual (maybe abstract) method named DoCleanup:

=== code begin ===

type
   TCleanup = class
   public
     procedure DoCleanup; virtual;
   end;

=== code end ===

Now assume there's a child class that does some very specific stuff in 
its DoCleanup method that relies on the order and where a user may only 
customize it a specific part:

=== code begin ===

type
   TWhateverCleanup = class
   private
     procedure Step1;
     procedure Step2;
     procedure Step3;
   protected
     procedure DoCustomCleanup; virtual;
   public
     procedure DoCleanup; override;
   end;

procedure TWhateverCleanup.DoCleanup;
begin
   Step1;
   Step2;
   DoCustomCleanup;
   Step3;
end;

=== code end ===

Now as the class is now someone that inherits from TWhateverCleanup 
might override DoCleanup, but adding something in front of or after the 
DoCleanup call would be wrong.

The ability to declare the method DoCleanup as final makes it clear to 
someone who inherits from the class, that no, you should not modify 
that, use a different way (in this case DoCustomCleanup) to customize 
its behavior.

And when I came upon this example I noticed that we use a similar scheme 
inside the compiler:

The tdef and tsym descendants have a virtual ppuwrite method. These 
classes have platform specific implementations so that e.g. the m68k 
tparavarsym descendant can write the register location for the syscall 
calling convention to the PPU. However due to how the writing to a PPU 
is implemented it's a bad idea to override the platform independant 
ppuwrite method, call inherited and then write the custom stuff. This 
had already led to problems in the past. Thus Jonas had introduced a new 
virtual ppuwrite_platform method that is supposed to be implemented by 
the platform specific descendants and made the platform independant 
ppuwrite implementations in the specific tdef and tsym implementations 
final so that no one that inherits from the tdef/tsym descendants gets 
the idea to mess inside that method again.

I've learned - during my research - that this is called "safe design".

Regards,
Sven


More information about the fpc-devel mailing list