Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 29, 2014 Why can't a method be virtual AND static at the same time? | ||||
---|---|---|---|---|
| ||||
This is a feature I've always missed in C++. Consider the code below: import std.stdio; interface Logger { void print(string msg); } class ConsoleLogger : Logger { static override void print(string msg) { writeln(msg); } } void main() { Logger logger = new ConsoleLogger; ConsoleLogger.print("Hello, World!"); } Such definition of ConsoleLogger fails to compile. I don't see any drawbacks to allowing this though, except the compiler would probably have to generate 2 methods internally. The way it is now, you have to either define each method twice or always create an instance. Or am I missing an obvious solution? |
January 29, 2014 Re: Why can't a method be virtual AND static at the same time? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Cejp | On Wednesday, 29 January 2014 at 13:30:54 UTC, Martin Cejp wrote: > This is a feature I've always missed in C++. Consider the code > below: > > import std.stdio; > > interface Logger { > void print(string msg); > } > > class ConsoleLogger : Logger { > static override void print(string msg) { > writeln(msg); > } > } > > void main() { > Logger logger = new ConsoleLogger; > > ConsoleLogger.print("Hello, World!"); > } I don't understand this code. You have a "logger" local variable, but don't use it. Do you want the compiler to autodetect which local variable to use by selecting one in the current scope? > Such definition of ConsoleLogger fails to compile. I don't see > any drawbacks to allowing this though, except the compiler would > probably have to generate 2 methods internally. > The way it is now, you have to either define each method twice or > always create an instance. > Or am I missing an obvious solution? What are you trying to accomplish? You can use object instances as namespaces, too. Example: ///////////////////////////////////////////////////////// import std.stdio; interface Logger { void print(string msg); } class ConsoleLoggerImpl : Logger { override void print(string msg) const { writeln(msg); } } const ConsoleLogger = new ConsoleLoggerImpl; void main() { ConsoleLogger.print("Hello, World!"); } ///////////////////////////////////////////////////////// Note that ConsoleLogger is "instantiated" at compile time, not runtime. To instantiate it at runtime, during initialization, you can use a static constructor. |
January 29, 2014 Re: Why can't a method be virtual AND static at the same time? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | On Wednesday, 29 January 2014 at 13:39:24 UTC, Vladimir Panteleev wrote: > On Wednesday, 29 January 2014 at 13:30:54 UTC, Martin Cejp wrote: >> This is a feature I've always missed in C++. Consider the code >> below: >> >> import std.stdio; >> >> interface Logger { >> void print(string msg); >> } >> >> class ConsoleLogger : Logger { >> static override void print(string msg) { >> writeln(msg); >> } >> } >> >> void main() { >> Logger logger = new ConsoleLogger; >> >> ConsoleLogger.print("Hello, World!"); >> } > > I don't understand this code. You have a "logger" local variable, but don't use it. Do you want the compiler to autodetect which local variable to use by selecting one in the current scope? > Oh no, these are supposed to be 2 independent usage examples, 1) being able to pass an instance of ConsoleLogger to a function/class expecting Logger and 2) being able to call a method without any instance at all. >> Such definition of ConsoleLogger fails to compile. I don't see >> any drawbacks to allowing this though, except the compiler would >> probably have to generate 2 methods internally. >> The way it is now, you have to either define each method twice or >> always create an instance. >> Or am I missing an obvious solution? > > What are you trying to accomplish? > > You can use object instances as namespaces, too. Example: > > ///////////////////////////////////////////////////////// > import std.stdio; > > interface Logger > { > void print(string msg); > } > > class ConsoleLoggerImpl : Logger > { > override void print(string msg) const > { > writeln(msg); > } > } > > const ConsoleLogger = new ConsoleLoggerImpl; > > void main() > { > ConsoleLogger.print("Hello, World!"); > } > ///////////////////////////////////////////////////////// > > Note that ConsoleLogger is "instantiated" at compile time, not runtime. To instantiate it at runtime, during initialization, you can use a static constructor. At compile time? Wow. Well, I guess this might work for me then :) (though there's no way around having to use 2 different names for the class and the const instance, is there?) |
January 29, 2014 Re: Why can't a method be virtual AND static at the same time? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Cejp | > Such definition of ConsoleLogger fails to compile. I don't see
> any drawbacks to allowing this though, except the compiler would
> probably have to generate 2 methods internally.
> The way it is now, you have to either define each method twice or
> always create an instance.
> Or am I missing an obvious solution?
Instead of defining it twice, you could alias the base version.
|
January 29, 2014 Re: Why can't a method be virtual AND static at the same time? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | On Wednesday, 29 January 2014 at 14:29:24 UTC, Tobias Pankrath wrote:
>> Such definition of ConsoleLogger fails to compile. I don't see
>> any drawbacks to allowing this though, except the compiler would
>> probably have to generate 2 methods internally.
>> The way it is now, you have to either define each method twice or
>> always create an instance.
>> Or am I missing an obvious solution?
>
> Instead of defining it twice, you could alias the base version.
What do you mean? The methods have different signatures (static x virtual)
By the way, what I want to do is have a class LocalFileSystem that can both
be passed as a FileSystem implementation and used directly,
without instantiation (LocalFileSystem.openFile)
|
January 29, 2014 Re: Why can't a method be virtual AND static at the same time? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Cejp | On Wednesday, 29 January 2014 at 13:30:54 UTC, Martin Cejp wrote:
> This is a feature I've always missed in C++. Consider the code
> below:
>
> import std.stdio;
>
> interface Logger {
> void print(string msg);
> }
>
> class ConsoleLogger : Logger {
> static override void print(string msg) {
> writeln(msg);
> }
> }
>
> void main() {
> Logger logger = new ConsoleLogger;
>
> ConsoleLogger.print("Hello, World!");
> }
>
> Such definition of ConsoleLogger fails to compile. I don't see
> any drawbacks to allowing this though, except the compiler would
> probably have to generate 2 methods internally.
> The way it is now, you have to either define each method twice or
> always create an instance.
> Or am I missing an obvious solution?
No, you are mixing concepts. Logger.print is a function that uses
a vtable and takes a hidden parameter this.
ConsoleLogger.print is a regular function that is not in a
vtable(because it is static) and does not take a hidden
parameter(again, because it is static).
So, when you do ConsoleLogger.print how the heck would the
compiler know which one you meant to use? While this might have a
solution, in some cases in general a virtual method REQUIRES a
virtual table and by using the keyword static on a function you
are saying it is not part of the virtual table.
Basically what you want is polymorphism here. Your two print
functions are different.
module main;
import std.stdio;
interface Logger {
void print(string msg);
}
class ConsoleLogger : Logger {
void print(string msg) { writeln(msg); }
static void print2(string msg) { writeln(msg); }
// Can we not rename print2 to print?
}
void main() {
Logger logger = new ConsoleLogger;
ConsoleLogger.print2("Hello, World!");
}
works because you used a different name for print(print2) so
there is no confusion.
One could say that since you "access" print from the class(and
not the object) that the compiler should use the static method
instead of the virtual.
This is actually different than saying print is both static and
non-static(virtual), which is impossible.
This all has to do with using the the same name of different
things just like overriding methods do(they are actually
different methods but use the same name because they have
different definitions and generally can be deduced). It may be
possible to do the same here. I don't know if there are any
pitfalls. You would still need to implement the interface method
print though, regardless.
The real issue comes from cases like this though:
module main;
import std.stdio;
interface Logger {
void print(string msg);
}
class ConsoleLogger : Logger {
void print(string msg) { writeln(msg); }
static void print(string msg) { writeln(msg); }
// assume this works
}
void main() {
auto logger = new ConsoleLogger;
logger.print("Hello, World!");
}
Do you know the issue now? (Again, there might be ways around it
but current that is not how the compiler thinks)
|
January 29, 2014 Re: Why can't a method be virtual AND static at the same time? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frustrated | On Wednesday, 29 January 2014 at 15:21:54 UTC, Frustrated wrote:
> No, you are mixing concepts. Logger.print is a function that uses
> a vtable and takes a hidden parameter this.
>
> ConsoleLogger.print is a regular function that is not in a
> vtable(because it is static) and does not take a hidden
> parameter(again, because it is static).
>
> So, when you do ConsoleLogger.print how the heck would the
> compiler know which one you meant to use? While this might have a
> solution, in some cases in general a virtual method REQUIRES a
> virtual table and by using the keyword static on a function you
> are saying it is not part of the virtual table.
>
Guess what: I DON'T CARE.
No really, I don't care at all about the implementation details.
If you look at it from the purely semantic view, there's no ambiguity: got an instance? call the instance method. no instance? call the static one.
Technically, yes, there would need to be two methods generated because of ABI differences, but this could be done behind the scenes. By making a method both override and static, you'd tell the compiler to do exactly that. Of course, the question is whether this would really be worth implementing and based on the reactions so far, I guess the answer is Not at all. I'm surprised that nobody else misses this feature, though.
|
January 29, 2014 Re: Why can't a method be virtual AND static at the same time? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Cejp | "Explicit better than implicit" |
January 29, 2014 Re: Why can't a method be virtual AND static at the same time? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Cejp | On Wednesday, 29 January 2014 at 15:30:38 UTC, Martin Cejp wrote:
> On Wednesday, 29 January 2014 at 15:21:54 UTC, Frustrated wrote:
>> No, you are mixing concepts. Logger.print is a function that uses
>> a vtable and takes a hidden parameter this.
>>
>> ConsoleLogger.print is a regular function that is not in a
>> vtable(because it is static) and does not take a hidden
>> parameter(again, because it is static).
>>
>> So, when you do ConsoleLogger.print how the heck would the
>> compiler know which one you meant to use? While this might have a
>> solution, in some cases in general a virtual method REQUIRES a
>> virtual table and by using the keyword static on a function you
>> are saying it is not part of the virtual table.
>>
> Guess what: I DON'T CARE.
> No really, I don't care at all about the implementation details.
> If you look at it from the purely semantic view, there's no ambiguity: got an instance? call the instance method. no instance? call the static one.
>
> Technically, yes, there would need to be two methods generated because of ABI differences, but this could be done behind the scenes. By making a method both override and static, you'd tell the compiler to do exactly that. Of course, the question is whether this would really be worth implementing and based on the reactions so far, I guess the answer is Not at all. I'm surprised that nobody else misses this feature, though.
I don't care either. It's not that I don't disagree with you but
I simply no longer care any more. I would care, and assuming such
a thing mattered then I could care. I just don't any more....
|
January 30, 2014 Re: Why can't a method be virtual AND static at the same time? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Cejp | On Wednesday, 29 January 2014 at 15:30:38 UTC, Martin Cejp wrote: You cannot override the static method because it isn't in the vtable and has a different calling convention; no this pointer is passed. > Technically, yes, there would need to be two methods generated because of ABI differences, but this could be done behind the scenes. By making a method both override and static, you'd tell the compiler to do exactly that. Of course, the question is whether this would really be worth implementing and based on the reactions so far, I guess the answer is Not at all. I'm surprised that nobody else misses this feature, though. So you want to overload the static method. Well you can do that (untested but should work): --- class A { static void f() {writeln(__PRETTY_FUNCTION__);} } class B : A { void f() {writeln(__PRETTY_FUNCTION__);} } class C : B { // Overrides from B, overloads from A override void f() {writeln(__PRETTY_FUNCTION__);} } void main () { auto b= new B(); auto c = new C(); A.f(); b.f(); c.f(); } --- Is this what you're trying to do? IMO though overloading base class methods should be avoided Cheers, ed |
Copyright © 1999-2021 by the D Language Foundation