Thread overview |
---|
September 11, 2017 Override with function overloads | ||||
---|---|---|---|---|
| ||||
In the code below, the second to the last line fails to compile. As far as I can tell it is because the override also overrides all overloads. I could imagine why it would occur with a virtual member function, but I would think it wouldn't be necessary with a final one. @system unittest { class Foo { final string bar(double d) { return ""; } void bar(int x) { x++; }; } class Foo2 : Foo { override void bar(int x) { } } Foo2 foo2 = new Foo2; foo2.bar(1); string x = foo2.bar(1.0); //error that bar is not callable with doubles //string x = foo2.Foo.bar(1.0); //this compiles } |
September 10, 2017 Re: Override with function overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to jmh530 | On 09/10/2017 08:14 PM, jmh530 wrote: > In the code below, the second to the last line fails to compile. As far > as I can tell it is because the override also overrides all overloads. I > could imagine why it would occur with a virtual member function, but I > would think it wouldn't be necessary with a final one. > > @system > unittest > { > class Foo > { > final string bar(double d) { return ""; } > void bar(int x) { x++; }; > } > > class Foo2 : Foo > { > override void bar(int x) { } > } > > Foo2 foo2 = new Foo2; > foo2.bar(1); > string x = foo2.bar(1.0); //error that bar is not callable with doubles > //string x = foo2.Foo.bar(1.0); //this compiles > } Here, the feature called "name hiding" is in effect. Foo2.bar hides all bars from Foo. This is to avoid "function hijacking"[1]. Ali [1] https://dlang.org/hijack.html |
September 11, 2017 Re: Override with function overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Monday, 11 September 2017 at 04:29:39 UTC, Ali Çehreli wrote: > > Here, the feature called "name hiding" is in effect. Foo2.bar hides all bars from Foo. This is to avoid "function hijacking"[1]. > > Ali > > [1] https://dlang.org/hijack.html I suppose my issue is that final should prevent function hijacking because I shouldn't be allowed to override string bar(double d) anyway. It shouldn't be a worry. I did see something in the bugzilla about hijack with default arguments. So I imagine it's not so easy to get right. https://issues.dlang.org/show_bug.cgi?id=6679 |
September 11, 2017 Re: Override with function overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to jmh530 | On Monday, 11 September 2017 at 15:13:25 UTC, jmh530 wrote:
> I suppose my issue is that final should prevent function hijacking because I shouldn't be allowed to override string bar(double d) anyway. It shouldn't be a worry.
It has nothing to do with overriding. Consider:
import std.stdio;
class A {
final void foo(int) {
writeln("A.foo(int)");
}
}
class B : A {
final void foo(long) {
writeln("B.foo(long)");
}
}
void main() {
B b = new B;
int n = 1;
b.foo(n);
}
That prints "B.foo(long)", even though foo() was called with an int (tbh, I'd say it's hijacking and shouldn't even compile, like it doesn't with virtual functions - try to remove finals). The compiler starts looking from B, finds name "foo" and tries that without looking any futher into base classes.
If you want that, you can do it manually:
class Foo2 : Foo
{
alias bar = super.bar; // bring Foo.bars in scope
override void bar(int x) { }
}
|
September 11, 2017 Re: Override with function overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to nkm1 | On Monday, 11 September 2017 at 17:59:25 UTC, nkm1 wrote:
> On Monday, 11 September 2017 at 15:13:25 UTC, jmh530 wrote:
>> I suppose my issue is that final should prevent function hijacking because I shouldn't be allowed to override string bar(double d) anyway. It shouldn't be a worry.
>
> It has nothing to do with overriding. Consider:
> [snip]
An interesting example. I'm not sure overriding is the issue so most as what is in the overload set. I think foo(int) is not part of the overload set yet. The compiler is able to cast the long to int and then call the one in class B without needing to look to the base class. The behavior is also the same if you use alias this (below).
Would there be any problems with final functions of inherited or alias this types being included in the overload set?
import std.stdio;
class A {
final void foo(int) {
writeln("A.foo(int)");
}
}
class B {
A a = new A;
alias a this;
final void foo(long)
{
writeln("B.foo(long)");
}
}
void main() {
B b = new B;
int n = 1;
b.foo(n);
}
|
September 11, 2017 Re: Override with function overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to jmh530 | On Monday, 11 September 2017 at 18:15:36 UTC, jmh530 wrote: > An interesting example. I'm not sure overriding is the issue so most as what is in the overload set. I think foo(int) is not part of the overload set yet. The compiler is able to cast the long to int and then call the one in class B without needing to look to the base class. The behavior is also the same if you use alias this (below). It's just an issue (not really an issue :) of name lookup. First, compiler searches for names, that is, for something called "foo". Then, when it finds "foo" (or several in the same scope), it does overload resolution on them. If those are wrong names, it just reports an error, for example: class A { final void foo(int) { writeln("A.foo(int)"); } } class B : A { string foo = "bar"; } void main() { B b = new B; int n = 1; b.foo(n); } While looking for names, it doesn't even care if "foo" is a function or whatever. > > Would there be any problems with final functions of inherited or alias this types being included in the overload set? > I don't know, maybe don't use alias this :) IMO, it's a really dubious feature... |
September 12, 2017 Re: Override with function overloads | ||||
---|---|---|---|---|
| ||||
Posted in reply to nkm1 | On Monday, 11 September 2017 at 20:40:30 UTC, nkm1 wrote:
>
> I don't know, maybe don't use alias this :) IMO, it's a really dubious feature...
I don't think it's an issue of alias this, per se. I think it's just something to be aware of and use your approach of aliasing as necessary. It's basically the same thing as using in C++.
|
Copyright © 1999-2021 by the D Language Foundation