Inheritance of things that are note instance methods
    Arafel via Digitalmars-d 
    digitalmars-d at puremagic.com
       
    Thu Aug  3 05:06:02 PDT 2017
    
    
  
Hi!
TL;DR: Inheritance seems to be a mess out of instance methods. Some 
things work, some other don't or not as expected, and apparently it 
isn't documented either [1].
Does somebody know how it's even *supposed* to work? Making it a bit 
more intuitive would also be nice :-)
Now, the long rant:
----
After a couple of threads in learn [2,3] related to how inheritance 
works in D out of the "usual" case of instance methods, I haven't been 
able to find in the spec [1] how things are supposed to be, and indeed I 
find the situation quite messy:
* Static functions are "virtual", i.e. there is a lookup of parent 
classes if it's not found. This is not documented, and I didn't even 
think it would work:
```
class A {
	static void foo() { };
}
class B : A { }
void main() {
	B.foo(); // This works, surprisingly
}
```
* However, there's no way for B.foo() to get its own class:
```
class A {
	static void foo() {
		import std.stdio;
		writeln(typeid(typeof(this)));
	}
}
class B : A { }
void main() {
	B.foo(); // This prints "A", I'd like to print "B"
}
```
This is a bit shocking, since the compiler must know for sure which 
class I'm from, and I can also make it explicit:
```
class A {
	static void foo(C)() {
		import std.stdio;
		writeln(typeid(C));
	}
}
class B : A { }
alias foo(C : A) = C.foo!C;
void main() {
	foo!B(); // This does indeed print "B"
}
```
I'd argue that since it's *already possible* (just inconvenient, 
unintuitive, and convoluted), "this" template parameters should be 
available everywhere, thus making something like this work out of the box:
```
class A {
	static void foo(this C)() {
		import std.stdio;
		writeln(typeid(typeof(this)));
		writeln(typeid(C));
	}
}
class B : A { }
void main() {
	B.foo(); // This should print "A" and then "B"
}
```
I think this is how most people would expect it to work, *given that 
B.foo() already works*. The other option would be to totally disable 
looking up static functions of parent classes.
* Finally, things get even more confusing with templates: a missing 
template will be looked up in "parent" classes, but a template that 
exists but is not instantiable won't:
```
class A {
	template foo(string s) if (s == "bar") {
		enum foo = 1;
	}
	enum bar = 1;
	
}
class B : A {
	template foo(string s) if (s == "baz") {
		enum foo = 2;
	}
	enum baz = 2;
}
void main() {
	import std.stdio;
	
	writeln(B.bar); // This works: bar is taken from A
	writeln(B.baz); // This also works, baz is directly in B
	//writeln(B.foo!"bar"); // This doesn't work: why?
	writeln(B.foo!"baz");
}
```
So all in all, I think it'd be nice to have some clear spec on what is 
supposed to work or not, and I also think that with just a couple of 
small changes things might greatly improve.
A.
[1]: https://dlang.org/spec/class.html
[2]: https://forum.dlang.org/post/olng6h$1e1s$1@digitalmars.com
[3]: https://forum.dlang.org/thread/axpqehyrvunzcjnrdccn@forum.dlang.org
    
    
More information about the Digitalmars-d
mailing list