www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Overriding of inherited class static methods?

reply Denis F <denis.feklushkin gmail.com> writes:
Hi!

Can anyone remind me why D doesn't provides overriding of static 
methods?
Is there some fundamental problem with this?

I think it would be great in itself and also intuitive.
Jul 21
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Tuesday, 21 July 2026 at 10:51:30 UTC, Denis F wrote:
 Hi!

 Can anyone remind me why D doesn't provides overriding of 
 static methods?
 Is there some fundamental problem with this?

 I think it would be great in itself and also intuitive.
How does it work? Overriding of a function works because you have a class instance. A static function has no instance. -Steve
Jul 21
next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
On Tuesday, 21 July 2026 at 13:11:37 UTC, Steven Schveighoffer 
wrote:
 On Tuesday, 21 July 2026 at 10:51:30 UTC, Denis F wrote:
 Hi!

 Can anyone remind me why D doesn't provides overriding of 
 static methods?
 Is there some fundamental problem with this?

 I think it would be great in itself and also intuitive.
How does it work? Overriding of a function works because you have a class instance. A static function has no instance. -Steve
```d import std; template innate(T,alias data,discrim...){ T innate=data; } template innateempty(T,discrim...){ T innateempty; } interface base{ int foo(int); void __hassetupfoo__(); TypeInfo mytypeinfo(); } mixin template setupfoo(alias foo){ TypeInfo mytypeinfo()=>typeid(typeof(this)); static this(){ alias store=innateempty!(int function(int)[TypeInfo],"foo"); //store[typeid(new typeof(this)).classinfo]=&foo; // ".classinfo applied to an interface gives the information for the interface, not the class it might be an instance of." WHY? store[(new typeof(this)).mytypeinfo]=&foo; } void __hassetupfoo__(){} } class A:base{ int foo(int i)=>i+2; static int foo_(int i)=>i+2; mixin setupfoo!(foo_); } class B:base{ int foo(int i)=>assert(0); static int foo_(int i)=>i*2; mixin setupfoo!(foo_); } int callfoo(base b,int i){ alias store=innateempty!(int function(int)[TypeInfo],"foo"); //return store[typeid(b).classinfo](i); return store[b.mytypeinfo](i); } unittest{ base bar; bar=new A(); bar.callfoo(3).writeln; bar=new B(); bar.callfoo(3).writeln; } ``` you just need to store it somewhere
Jul 21
prev sibling parent reply ShadoLight <ettienne.gilbert gmail.com> writes:
On Tuesday, 21 July 2026 at 13:11:37 UTC, Steven Schveighoffer 
wrote:
 On Tuesday, 21 July 2026 at 10:51:30 UTC, Denis F wrote:
 Hi!

 Can anyone remind me why D doesn't provides overriding of 
 static methods?
 Is there some fundamental problem with this?

 I think it would be great in itself and also intuitive.
How does it work? Overriding of a function works because you have a class instance. A static function has no instance. -Steve
Since he is specifically asking about static methods, maybe the OP is thinking of 'overloading', rather than 'overriding' - currently this already works: ```D class B { public static int bar(int y) { return 20*y; } } class D : B { public static int bar(int y) { return 30*y; } } assert(B.bar(2)==40); assert(D.bar(2)==60); ``` But this of course is not the same behavior as 'overriding' eg. if you do this... ```D B d = new D; ``` ... and call the static method through the instance, the function in class B will get called i.e. you will get... ```D assert(d.bar(2)==40); ``` ... which is not the polymorphic behavior you get when overriding.
Jul 21
parent reply Denis F <denis.feklushkin gmail.com> writes:
On Tuesday, 21 July 2026 at 14:50:29 UTC, ShadoLight wrote:

 Since he is specifically asking about static methods, maybe the 
 OP is thinking of 'overloading'
Yes, exactly! And, as shown above, this could work, right? And it would be good from a code maintenance point: if a method could easily be converted to static or vice versa during the code's lifetime it will be convient, I think (These thoughts are inspired by contemplation of static methods inside of `core.thread.threadbase.ThreadBase` and `core.thread.osthread.Thread`)
Jul 22
parent reply ShadoLight <ettienne.gilbert gmail.com> writes:
On Wednesday, 22 July 2026 at 08:05:48 UTC, Denis F wrote:
 And, as shown above, this could work, right?
This would depend what you want to achieve.
 And it would be good from a code maintenance point: if a method 
 could easily be converted to static or vice versa during the 
 code's lifetime it will be convient, I think
"converting to static or vice versa ... easily" comes with some 'gotcha's' you have to keep in mind. Consider a class D inheriting from a class B: ```D class B { public int foo(int x) { return 2*x; } } class D : B { public override int foo(int x) { return 3*x; } } ``` Consider what the idea behind polymorphic behavior is i.e. for example, lets create 2 instances of class D, but with one being of the base "type"... ```D B b = new D; D d = new D; ``` ...and both cases will call the overridden foo function: ```D assert(b.foo(2)==6); //PASS assert(d.foo(2)==6); //PASS ``` Now consider what happens if you convert foo from virtual to static: ```D class B { public static int foo(int x) { return 2*x; } } class D : B { public static int foo(int x) { return 3*x; } } ``` If you keep the rest of the code the same... ```D B b = new D; D d = new D; assert(b.foo(2)==6); //FAIL assert(d.foo(2)==6); //PASS ``` ... instance b will call it's own version of foo, and the assert will fail. TLDR: Changing a virtual method from virtual to static or vice versa can (and probably will) affect downstream code.
Jul 22
parent reply Denis F <denis.feklushkin gmail.com> writes:
On Wednesday, 22 July 2026 at 09:13:59 UTC, ShadoLight wrote:

 TLDR: Changing a virtual method from virtual to static or vice 
 versa can (and probably will) affect downstream code.
Your sample lack of override keyword on D.foo definition. I think this can be used to differentiate such cases.
Jul 22
parent reply ShadoLight <ettienne.gilbert gmail.com> writes:
On Wednesday, 22 July 2026 at 12:04:36 UTC, Denis F wrote:
 Your sample lack of override keyword on D.foo definition. I 
 think this can be used to differentiate such cases.
OK, so you are proposing this: ```D class B { public static int foo(int x) { return 2*x; } } class D : B { public static override int foo(int x) { return 3*x; } } ``` This cannot work as static function addresses are not specified in the vtable, hence they cannot be overridden. This will also be a breaking change as, currently, you can call a static function through the instance pointer or the class name like this: ```D D b = new D; assert(b.foo(2) == D.foo(2)); ``` Both ```b.foo(2)``` and ```D.foo(2)``` calls here are equivalent and call the same "free function" ```foo``` (without the need for the ```this``` pointer to be passed implicitly). If you then propose to add static functions to the vtable to allow them to be overridden - that would then in turn cause static functions not to be callable using the class name (```D.foo(..)``` above) as the vtable is associated with the instance of the class (which is passed via the implicit ```this``` pointer), and not the class definition. In such a case which instance of D does ```D.foo(..)``` refer to? This would also mean static functions will have to be called, as is the case for virtual functions today, through an extra indirection (compared to normal static functions today) - with performance implications if you go from "static" to "static override". In fact they would then become practically indistinguishable from virtual functions itself. There are other issues as well, for example can a "static override" method access a static data member of a class? This would change the concept of "static functions" in D to be completely different to the classical concept that all object cannot imagine that you will get any support for this idea. Static methods are quite simply "free functions" with a slightly modified calling syntax (and affected by the visibility and access rules of their "owner" class, etc...).
Jul 22
parent reply Denis F <denis.feklushkin gmail.com> writes:
On Wednesday, 22 July 2026 at 14:03:53 UTC, ShadoLight wrote:

 If you then propose to add static functions to the vtable to 
 allow them to be overridden - that would then in turn cause 
 static functions not to be callable using the class name 
 (```D.foo(..)``` above) as the vtable is associated with the 
 instance of the class (which is passed via the implicit 
 ```this``` pointer),
Oblivous, this should be a special compile-time "vtbl" as proposed by monkyyy above
Jul 23
parent reply ShadoLight <ettienne.gilbert gmail.com> writes:
On Thursday, 23 July 2026 at 10:28:40 UTC, Denis F wrote:
 On Wednesday, 22 July 2026 at 14:03:53 UTC, ShadoLight wrote:

 If you then propose to add static functions to the vtable to 
 allow them to be overridden - that would then in turn cause 
 static functions not to be callable using the class name 
 (```D.foo(..)``` above) as the vtable is associated with the 
 instance of the class (which is passed via the implicit 
 ```this``` pointer),
Oblivous, this should be a special compile-time "vtbl" as proposed by monkyyy above
monkyyys proposal does not give you a "special compile-time "vtbl"". And monkyyy's solution neither gives you 'overriding' behavior of a static method in a derived class. He merely showed, using some template wizardry, that he can 'redirect' the call to the virtual method that implements the abstract method declared in an *interface*, to a static method in the same class. This does not give you what you originally asked namely "Can anyone remind me why D doesn't provides overriding of static methods?" - There is no static method in monkyyy's ```base``` class. In fact, it is not even a class, it is an interface. - The hierarchy can only be one deep eg. everything needs to be derived from ```base```. For example, class B cannot be derived from class A. This will be extremely limiting, even discounting the ton of template boilerplate this requires. - You have to call ```callfoo(..)``` on the instance, and not ```foo(..)```, yet... - ... you still need a virtual ```foo(..)``` implemented in the class to satisfy the ```foo``` declaration in the interface. - The static method cannot be the same name (```foo``` here) as the interface method being "overridden". But, **most of all**, if you accidently (using monkyyy's code as an example) call... ```D bar.foo(3).writeln; ``` ... instead of... ```D bar.callfoo(3).writeln; ``` ... the virtual ```foo``` will be called, and not the static ```foo_```. This code is not only confusing to read and overly complex for what it delivers - it will be bug-prone as hell since a lot of people will call ```foo``` on the instance, instead of ```callfoo```. This is no implementable general solution. This "overriding of static methods" idea is such a non-starter that I assumed you meant "overloading", rather than "overriding" - which you in fact confirmed. And, yet, since then you have kept pushing this conversation back towards "overriding" ... it is a bad idea and I've tried to show you some of the implications. If you have some ideas how this can be a good idea then show how it will work, etc.
Jul 23
next sibling parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Thursday, 23 July 2026 at 14:30:39 UTC, ShadoLight wrote:
 On Thursday, 23 July 2026 at 10:28:40 UTC, Denis F wrote:
 On Wednesday, 22 July 2026 at 14:03:53 UTC, ShadoLight wrote:

 If you then propose to add static functions to the vtable to 
 allow them to be overridden - that would then in turn cause 
 static functions not to be callable using the class name 
 (```D.foo(..)``` above) as the vtable is associated with the 
 instance of the class (which is passed via the implicit 
 ```this``` pointer),
Oblivous, this should be a special compile-time "vtbl" as proposed by monkyyy above
monkyyys proposal does not give you a "special compile-time "vtbl""
`innateempty!(int function(int)[TypeInfo],"foo");` is constructed at `unittest time` Its after compile time but before user's prespection of runtime; ideally this would be moved into the compilers linking stage or something.
 This code is not only confusing to read and overly complex for 
 what it delivers - it will be bug-prone as hell since a lot of 
 people will call foo on the instance, instead of callfoo. This 
 is no implementable general solution.
 How does it work? -Steve
it seems to me, that if a class has a `static int foo(int)` in its interface, it could have an "innate" `int function(int)[TypeInfo]` vtable that glues it together the point of showing code "that works", is to prove its possible, of course the compiler devs would look at that as see where to take short cuts inside the compiler and make a better api then doing it manually
Jul 23
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 24/07/2026 7:33 AM, monkyyy wrote:
 it seems to me, that if a class has a |static int foo(int)| in its 
 interface, it could have an "innate" |int function(int)[TypeInfo]| 
 vtable that glues it together
 
 the point of showing code "that works", is to prove its possible, of 
 course the compiler devs would look at that as see where to take short 
 cuts inside the compiler and make a better api then doing it manually
Its called a symbol table, D doesn't make use of them like older languages do. However symbol lookup can handle this just fine, no need for new infrastructure.
Jul 23
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Thursday, 23 July 2026 at 20:24:41 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 However symbol lookup can handle this just fine,
my understanding of what op wants is this: ```d import std; interface base{ static int foo(int); } class A:base{ static int foo(int i)=>i+2; } class B:base{ static int foo(int i)=>i*2; } unittest{ base bar=new A(); auto f=&bar.foo; f(3).writeln; } ``` this doesn't link maybe op was thinking of aa's redbook "policys" but runtime, idk [insert an oo is bad rant here] I think your "Linker list"s needs to be generalized to pseudo compiletime appended list, because look its a "type to runtime value lookup table" *again*, thats been some of my problems, its your linker lists and if Im right about what op wants it could be reframmed as an `int function(int)[TypeInfo]` issue
Jul 23
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 24/07/2026 9:07 AM, monkyyy wrote:
 I think your "Linker list"s needs to be generalized to pseudo 
 compiletime appended list, because look its a "type to runtime value 
 lookup table" /again/, thats been some of my problems, its your linker 
 lists and if Im right about what op wants it could be reframmed as an | 
 int function(int)[TypeInfo]| issue
You can't read a linker list at compile time. It only exists in a usable state at runtime after the linker has put it all together. As for your example, yeah thats a vtable all right, nothing static about it.
Jul 23
parent monkyyy <crazymonkyyy gmail.com> writes:
On Thursday, 23 July 2026 at 21:22:33 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 On 24/07/2026 9:07 AM, monkyyy wrote:
 I think your "Linker list"s needs to be generalized to pseudo 
 compiletime appended list, because look its a "type to runtime 
 value lookup table" /again/, thats been some of my problems, 
 its your linker lists and if Im right about what op wants it 
 could be reframmed as an | int function(int)[TypeInfo]| issue
You can't read a linker list at compile time.
https://forum.dlang.org/post/qbwpgeqpwdllfbadrbor forum.dlang.org
 As for your example, yeah thats a vtable all right, nothing 
 static about it.
static is very overloaded, I use it when the compiler complains about not finding `this` or dual context whatever, maybe op tried making a dual context issue go away and got two worthless error messages that would be usually solved by swapping staticness
Jul 23
prev sibling parent reply ShadoLight <ettienne.gilbert gmail.com> writes:
On Thursday, 23 July 2026 at 21:07:32 UTC, monkyyy wrote:

 my understanding of what op wants is this:

 ```d
 import std;

 interface base{
     static int foo(int);
 }
 class A:base{
     static int foo(int i)=>i+2;
 }
 class B:base{
     static int foo(int i)=>i*2;
 }
 unittest{
     base bar=new A();
     auto f=&bar.foo;
     f(3).writeln;
 }
 ```
Having a static method declared in a interface and then 'implementing' it in a derived class is not really 'overriding' in the context of this question. What the OP is saying/implying is this: ```D import std; class base{ static int foo(int i)=>i+1; } class A:base{ static override int foo(int i)=>i+2; //This is the request i.e. add polymorphic // behavior here } class B:base { static int foo(int i)=>i*2; //This already works, but not polymorphically } unittest{ base b1=new A(); assert(b1.foo(2) == 4); // Polymorphic behavior... not currently possible base b2=new B(); assert(b2.foo(2) == 3); // Not polymorphic behavior... this currently works } ``` There are a lot of issues with this. For example, what should happen here? ```D class base{ static int count; static int foo(int i)=>count+1; } class A:base{ static override int foo(int i)=>count+2; //This is the request i.e. add polymorphic // behavior here } unittest{ base b1=new A(); int x = b1.foo(2); } ``` How would you handle a static member like ```count``` now? Then these is the issue of calling the static method through the name i.e. if you have multiple instances of type A... ```D base b1 = A(), b2 = A(); ``` ...how is ```A.foo(2)``` handled in this case ... which instance does it refer to? I don't think adding polymorphic behavior to static methods can be done in a way that is sensible - it will be massively confusing.
Jul 24
parent monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 24 July 2026 at 08:09:14 UTC, ShadoLight wrote:
 
 ```D
 class base{
     static int count;
     static int foo(int i)=>count+1;
 }
 ```
 How would you handle a static member like ```count``` now?
I dont use classes, and dont care, but as a static int that should be a effectively a global and be "god object", if you remove static from int, then static on foo shouldnt work because the most important part of static is removing `this` and `context` errors.
 Then these is the issue of calling the static method through 
 the name i.e. if you have multiple instances of type A...
only to oo theory, I actively seek out ways to make more global state
 I don't think adding polymorphic behavior to static methods can 
 be done in a way that is sensible - it will be massively 
 confusing.
"the expression problem" has 2 common views, oo wants a "rotation" functional typethoery and while I dont have a way to articulate it imperative is of course out there with all of game dev wanting very very different things; so a implied 3rd. Big "static"(made global) values is just part of "imperative" and real world polymorphism. If your in a tourist trap the shop keeps will likely accept 2 currency's, the two currencies are "polymorphic" of "money" in reference to a global exchange rate which is just "bad style" for oo's encapsulation and functional purity; blah blah, monads. But real world, you have the option of not caring, the shop keeper dealing with the "polymorphic currency's" is just going to keep two tallys, have the cash register hooked up to a daily spot price and when doing their numbers setup an excel cell to grab the exchange rate and while they will lose a penny here or there it will be fine. Youd want to minimize unnecessary conversions between the dual currency's, but hiding it, outlawing it citing math and telling the shopkeep (in their 2nd language) about monads; would be silly. A tiny bit of global state can drastically simplify a problem. Its ok that most of excel is "pure" but deleting the features that grab magic numbers from the internet would make for a worse product. If you want the class keyword to be owned by oo, ok; but I dont see any of this as hard to deal with or very scary.
Jul 24
prev sibling parent Denis F <denis.feklushkin gmail.com> writes:
On Thursday, 23 July 2026 at 14:30:39 UTC, ShadoLight wrote:
 If you have some ideas how this can be a good idea then show 
 how it will work, etc.
No. I just wanted to spark some kind of discussion, which is what happened. Thank you!
Jul 24
prev sibling next sibling parent user1234 <user1234 12.de> writes:
On Tuesday, 21 July 2026 at 10:51:30 UTC, Denis F wrote:
 Hi!

 Can anyone remind me why D doesn't provides overriding of 
 static methods?
 Is there some fundamental problem with this?

 I think it would be great in itself and also intuitive.
per-class static variables or per-class static methods sound good in first place but actually this feature requires an indirection, i.e a lookup in a the virtual table.
Jul 22
prev sibling parent DefinitelyNotAVtable <DefinitelyNotAVtable gmail.com> writes:
On Tuesday, 21 July 2026 at 10:51:30 UTC, Denis F wrote:
 Hi!

 Can anyone remind me why D doesn't provides overriding of 
 static methods?
 Is there some fundamental problem with this?

 I think it would be great in itself and also intuitive.
If static members became polymorphic, static would stop meaning "belongs to the type" and would start meaning "belongs to the type... unless the object has a better idea." Of course, D has some history here ... since a private/protected member also "belongs to the type... unless other code outside the type has a better idea." So who knows, maybe D will do this as well, one day - just to confuse us OO programmers even more.
Jul 23