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