Jump to content
Lars Fosdal

Class methods and the effects of the static keyword

Recommended Posts

The output of the test app below surprised me.

 

Can someone point me to the documentation that says that if a static class method calls a virtual class method, only the base class virtual method will be called, and not the override?

 

TParent.HasOverride:            I said no to overrides
TParent.HasOverride Static:     I said no to overrides
TChild.HasOverride:             I haz overridez
TChild.HasOverride Static:      I said no to overrides
Press Enter:

 

 

program StaticClassMethodCallingVirtualClassMethod;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  TParent = class
  public
    class function OverrideMe: Boolean; virtual;
    class function HasOverride: string;
    class function HasOverrideStatic: string; static;
    class procedure Test<T: TParent, constructor>;
  end;

  TChild = class(TParent)
  public
    class function OverrideMe: Boolean; override;
  end;

{ TParent }

class function TParent.HasOverride: string;
begin
  if OverrideMe
   then Result := 'I haz overridez'
    else Result := 'I said no to overrides';
end;

class function TParent.HasOverrideStatic: string;
begin
  if OverrideMe
   then Result := 'I haz overridez'
    else Result := 'I said no to overrides';
end;

class function TParent.OverrideMe: Boolean;
begin
  Result := False;
end;

class procedure TParent.Test<T>;
begin
  Writeln(T.ClassName, '.HasOverride: '^I^I, T.HasOverride);
  Writeln(T.ClassName, '.HasOverride Static: '^I, T.HasOverrideStatic);
end;

{ TChild }

class function TChild.OverrideMe: Boolean;
begin
  Result := True;
end;

begin
  try
    try
      TParent.Test<TParent>;
      TParent.Test<TChild>;
    except
      on E: Exception do
        Writeln(E.ClassName, ': ', E.Message);
    end;
  finally
    Write('Press Enter: ');
    Readln;
  end;
end.

 

Share this post


Link to post

OK, that makes sense.  But - it is a bit of a pitfall, since you can call virtual methods from the static one - and not get a warning about it.

Share this post


Link to post
7 hours ago, Lars Fosdal said:

it is a bit of a pitfall, since you can call virtual methods from the static one - and not get a warning about it.

Because it still has access to the VMT of its own class type and its ancestors, so will still respect virtual dispatch for that part of the class tree.  It just does not have access to the VMT of any derived classes.

 

But, to be honest, in what use-case is it ever useful to call a virtual class method inside of a static class method in practice?  The whole point of static is to ignore particular instances, and polymorphism is all about focusing on specific instances.

Share this post


Link to post
8 minutes ago, Remy Lebeau said:

But, to be honest, in what use-case is it ever useful to call a virtual class method inside of a static class method in practice

Lars understands that, I think, and wonders why the compiler doesn't take the same view and issue a warning. 

  • Like 3

Share this post


Link to post

Changing that would raise some warnings in existing potentially defect code and some people don't want that :classic_huh:

 

Similar to being able to call non virtual class methods on instances

Edited by Stefan Glienke

Share this post


Link to post
3 minutes ago, Stefan Glienke said:

Changing that would raise some warnings in existing potentially defect code and some people don't want that :classic_huh:

 

Similar to being able to call non virtual class methods on instances

Those people could always disable that warning for code where they don't want to see it. Not having such a warning means that the rest of us doesn't get the benefit.

Share this post


Link to post
4 minutes ago, dummzeuch said:

Those people could always disable that warning for code where they don't want to see it. Not having such a warning means that the rest of us doesn't get the benefit.

Don't tell me - but this the almighty excuse brought up by the decision makers almost every time some issue like this is brought up - "but what about existing code" - like for that dreaded "directly passing result of ctor call to interface parameter issue" - what about existing code? Well existing code is most likely suffering from a defect.

 

The stupidity of the Delphi compiler in almost every aspect and the unwillingness to change anything significant on that is making me furious!

  • Like 7
  • Haha 1

Share this post


Link to post
On 9/30/2019 at 4:39 AM, Stefan Glienke said:

Don't tell me - but this the almighty excuse brought up by the decision makers almost every time some issue like this is brought up - "but what about existing code" - like for that dreaded "directly passing result of ctor call to interface parameter issue" - what about existing code? Well existing code is most likely suffering from a defect.

 

The stupidity of the Delphi compiler in almost every aspect and the unwillingness to change anything significant on that is making me furious!

You're reminding me of something written by Dennis Ritchie about operator precedence in C. At one point early on they wanted to change it, but Ritchie said "We can't; there's almost a million lines of C code out there!" :classic_biggrin: He wrote that in retrospect they should have made the change. Contrast this with the creator of Python, Guido Van Rossum, when talking about breaking compatibility to change how Unicode strings were handled. I don't have the exact quote, but it went something like  "All the lines of Python ever written pale in comparison to the number of lines of Python yet to be written".

 

Quote

The stupidity of the Delphi compiler in almost every aspect and the unwillingness to change anything significant on that is making me furious!

This gets into the touchy subject of how many people are writing new code in Delphi versus how many are maintaining legacy code. Even with C++Builder they brought the 32bit compiler up to C++17 first, saying you'd be surprised how much 32bit code is being maintained by C++Builder users.

Share this post


Link to post
18 hours ago, Joseph MItzen said:

You're reminding me of something written by Dennis Ritchie about operator precedence in C

That made me curious and I looked it up:

 

https://stackoverflow.com/questions/54733581/which-operators-in-c-have-wrong-precedence

 

The bit operators in C indeed have a non-optimal operator precedence.

 

I'm also more in favor of breaking changes in programming languages. C++ has tools that do code modernization like the modernization module of clang-tidy: https://clang.llvm.org/extra/clang-tidy/index.html

 

I like how in C++ standards they first deprecated a feature in a standard version and then remove it in the next version of the standard. This gives compilers the change to show warnings for the deprecated feature and the users time to fix their code.

Edited by Jens Mühlenhoff
  • Like 1

Share this post


Link to post
Guest
On 10/1/2019 at 6:14 PM, Joseph MItzen said:

You're reminding me of something written by Dennis Ritchie about operator precedence in C. At one point early on they wanted to change it, but Ritchie said "We can't; there's almost a million lines of C code out there!" :classic_biggrin: He wrote that in retrospect they should have made the change. Contrast this with the creator of Python, Guido Van Rossum, when talking about breaking compatibility to change how Unicode strings were handled. I don't have the exact quote, but it went something like  "All the lines of Python ever written pale in comparison to the number of lines of Python yet to be written".

Another keen example; i always "hated" apple. Always promoted Windoze. Then when Apple forced the migration from "System X" to "OS X" apple users that always had bullied me for years were crying because of backward un-compatibility. THAT was when i became Apple-positive, a bit... i told them that if you carry all of your technical debt for all times things will eventually break; that what Apple was doing was essential. M$ did it the other way around (not strange commercially thinking because of huge existing application-base for Windoze). But sometimes you just have to take a new leap. Delphi OP is riddled with ambiguous meaning for basic stuff like "[". Changing that will hurt a lot. Very much hurt. Hurt-locker.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×