digitalmars.D - Shouldn't private methods be virtual too?
- Michel Fortin (29/29) Jun 10 2008 The following example prints "Base.foo" (using GDC 0.24), even though
- Jarrett Billingsley (22/43) Jun 10 2008 I would expect an error too. In most languages with this kind of protec...
- Steven Schveighoffer (8/31) Jun 10 2008 In answer to your subject, no. Private methods are methods used by a cl...
- Robert Fraser (5/35) Jun 10 2008 I agree, but last time I asked this it seemed like an unwinnable battle
- Jarrett Billingsley (5/9) Jun 10 2008 I'll agree with you on "package". "package" should be entirely a visibi...
- Michel Fortin (13/16) Jun 10 2008 Yeah, but private and package in D don't apply only to derived classes.
- Robert Fraser (6/16) Jun 10 2008 "protected" and "package" are non-equivalent overlapping sets; neither
- Michel Fortin (27/34) Jun 10 2008 Ok, so we're two to think protection attributes should be orthogonal
- Robert Fraser (17/55) Jun 10 2008 I've thought a lot about this issue, and I believe you're right they
- Robert Fraser (4/5) Jun 10 2008 Sorry, that probably came off as a bit harsh. Everyone has one or two
The following example prints "Base.foo" (using GDC 0.24), even though we have a Derived object and Derived's foo is declared as overriding Base's. Is that expected behaviour? module test.privatevirtualfunction; class Base { private void foo() { writefln("Base.foo"); } } class Derived : Base { override private void foo() { writefln("Derived.foo"); } } int main(char[][] args) { Base base = new Derived; base.foo(); return 0; } I understand that private currently makes the method non-virtual. I think this would be fine with the C++ private concept where it limits the member's usage to the current class, but I believe in D, where private only limits usage to the current module, you should be able to override that method in any class defined in the same module. If that's not the case, then you should at the very least get an error with the above code. Making Base's method public or protected changes the output to "Derived.foo" as I'd expect. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 10 2008
"Michel Fortin" <michel.fortin michelf.com> wrote in message news:g2lnj9$1ig9$1 digitalmars.com...The following example prints "Base.foo" (using GDC 0.24), even though we have a Derived object and Derived's foo is declared as overriding Base's. Is that expected behaviour? module test.privatevirtualfunction; class Base { private void foo() { writefln("Base.foo"); } } class Derived : Base { override private void foo() { writefln("Derived.foo"); } } int main(char[][] args) { Base base = new Derived; base.foo(); return 0; } I understand that private currently makes the method non-virtual. I think this would be fine with the C++ private concept where it limits the member's usage to the current class, but I believe in D, where private only limits usage to the current module, you should be able to override that method in any class defined in the same module. If that's not the case, then you should at the very least get an error with the above code.I would expect an error too. In most languages with this kind of protection scheme, overriding a base class method with a method that is more protected is an error. It is in Java: class Fark { public void foo() { } } public class Bark extends Fark { protected void foo() { } } Gives the error "foo() in Bark cannot override foo() in Fark; attempting to assign weaker access privileges; was public." And if my memory serves me, Private methods should always be final. They cannot be overridden by derived classes, even if they can be accessed by classes in the same module.
Jun 10 2008
"Michel Fortin" wroteThe following example prints "Base.foo" (using GDC 0.24), even though we have a Derived object and Derived's foo is declared as overriding Base's. Is that expected behaviour? module test.privatevirtualfunction; class Base { private void foo() { writefln("Base.foo"); } } class Derived : Base { override private void foo() { writefln("Derived.foo"); } } int main(char[][] args) { Base base = new Derived; base.foo(); return 0; } I understand that private currently makes the method non-virtual. I think this would be fine with the C++ private concept where it limits the member's usage to the current class, but I believe in D, where private only limits usage to the current module, you should be able to override that method in any class defined in the same module. If that's not the case, then you should at the very least get an error with the above code. Making Base's method public or protected changes the output to "Derived.foo" as I'd expect.In answer to your subject, no. Private methods are methods used by a class that declares it only, not by derived classes. That is the expectation that an author should have when declaring a method private. If you want a method to be overridable by derived classes, declare it protected. In answer to your example, I agree there should be an error if you declare a method as 'override private'. -Steve
Jun 10 2008
Michel Fortin wrote:The following example prints "Base.foo" (using GDC 0.24), even though we have a Derived object and Derived's foo is declared as overriding Base's. Is that expected behaviour? module test.privatevirtualfunction; class Base { private void foo() { writefln("Base.foo"); } } class Derived : Base { override private void foo() { writefln("Derived.foo"); } } int main(char[][] args) { Base base = new Derived; base.foo(); return 0; } I understand that private currently makes the method non-virtual. I think this would be fine with the C++ private concept where it limits the member's usage to the current class, but I believe in D, where private only limits usage to the current module, you should be able to override that method in any class defined in the same module. If that's not the case, then you should at the very least get an error with the above code. Making Base's method public or protected changes the output to "Derived.foo" as I'd expect.I agree, but last time I asked this it seemed like an unwinnable battle (everyone else said private should imply "final"). More controversial was whether "package" should imply "final" (which it does now, but I think it should not).
Jun 10 2008
"Robert Fraser" <fraserofthenight gmail.com> wrote in message news:g2n15d$2jo8$1 digitalmars.com...I agree, but last time I asked this it seemed like an unwinnable battle (everyone else said private should imply "final"). More controversial was whether "package" should imply "final" (which it does now, but I think it should not).I'll agree with you on "package". "package" should be entirely a visibility attribute. More or less it would function like 'protected' as long as the deriving class were in the same package; and 'private' if it weren't. Sigh.
Jun 10 2008
On 2008-06-10 21:58:55 -0400, "Jarrett Billingsley" <kb3ctd2 yahoo.com> said:I'll agree with you on "package". "package" should be entirely a visibility attribute. More or less it would function like 'protected' as long as the deriving class were in the same package; and 'private' if it weren't. Sigh.Yeah, but private and package in D don't apply only to derived classes. Private means that any code in the same module may access the method, and package means any code in the same package may access the method. This is to avoid adding something alike the friend C++ keyword (anything in the same module is always a friend). There's noting to make a member "class-private" in D. By the way, protected methods can also be accessed from outside the class and its derivative if you're in the same module. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 10 2008
Jarrett Billingsley wrote:"Robert Fraser" <fraserofthenight gmail.com> wrote in message news:g2n15d$2jo8$1 digitalmars.com..."protected" and "package" are non-equivalent overlapping sets; neither one a subset of the other. "package" means anything in the package can access it, whether it's in a derived class or not. "protected" means that only thing in the derived class (or the same module as the item in question) should be able to access it, no matter what package they're in.I agree, but last time I asked this it seemed like an unwinnable battle (everyone else said private should imply "final"). More controversial was whether "package" should imply "final" (which it does now, but I think it should not).I'll agree with you on "package". "package" should be entirely a visibility attribute. More or less it would function like 'protected' as long as the deriving class were in the same package; and 'private' if it weren't. Sigh.
Jun 10 2008
On 2008-06-10 19:02:13 -0400, Robert Fraser <fraserofthenight gmail.com> said:Ok, so we're two to think protection attributes should be orthogonal with the final attribute of a member function, although I can't say I'm strongly in favor of one or the other. Package and private are pretty much the same thing: one makes the function accessible to the current module only, the other makes the function accessible to the current package only. If one has the side effect of making the function final, then the other should too if we are to preserve consistency. As a side note, it's pretty amusing to see that even this compiles perfectly fine: class Base { final package void foo() { writefln("Base.foo"); } } class Derived : Base { override final package void foo() { writefln("Derived.foo"); } } In Functions[1], it is said that "Functions marked as final may not be overridden in a derived class, unless they are also private", so I take it to mean that it is correct to override a final private function in derived class, and by extension this is true for package functions too, and thus, there are no bugs here. Funny, isnt' it? [1]: http://www.digitalmars.com/d/2.0/function.html -- Michel Fortin michel.fortin michelf.com http://michelf.com/Making Base's method public or protected changes the output to "Derived.foo" as I'd expect.I agree, but last time I asked this it seemed like an unwinnable battle (everyone else said private should imply "final"). More controversial was whether "package" should imply "final" (which it does now, but I think it should not).
Jun 10 2008
Michel Fortin wrote:On 2008-06-10 19:02:13 -0400, Robert Fraser <fraserofthenight gmail.com> said:I've thought a lot about this issue, and I believe you're right they /should/ be consistent here -- a "package" is a limited set of modules controlled (supposedly) by one programmer or a small team, so API changes aren't a deal here. However, if there's going to be some nonsensical restriction that "private" implies "final" making "package" imply "final" is simply too strong of a restriction. There's often times you want to expose a method within a package for convenience, but don't want it to be part of the public API. Since most class overriding takes place within a package, restricting there's enough of a need for virtual package function to justify the inconsistency. I'd rather make it so that the concepts were orthogonal , though.Ok, so we're two to think protection attributes should be orthogonal with the final attribute of a member function, although I can't say I'm strongly in favor of one or the other. Package and private are pretty much the same thing: one makes the function accessible to the current module only, the other makes the function accessible to the current package only. If one has the side effect of making the function final, then the other should too if we are to preserve consistency.Making Base's method public or protected changes the output to "Derived.foo" as I'd expect.I agree, but last time I asked this it seemed like an unwinnable battle (everyone else said private should imply "final"). More controversial was whether "package" should imply "final" (which it does now, but I think it should not).As a side note, it's pretty amusing to see that even this compiles perfectly fine: class Base { final package void foo() { writefln("Base.foo"); } } class Derived : Base { override final package void foo() { writefln("Derived.foo"); } } In Functions[1], it is said that "Functions marked as final may not be overridden in a derived class, unless they are also private", so I take it to mean that it is correct to override a final private function in derived class, and by extension this is true for package functions too, and thus, there are no bugs here. Funny, isnt' it? [1]: http://www.digitalmars.com/d/2.0/function.htmlJava figured out perfectly good semantics for package-protection years ago. Having "protected" and "private" accessible within the same module throws a wrench into it (i.e. we can't totally copy it), but why we need to tie concepts lie protection and virtuality together is beyond me.
Jun 10 2008
Robert Fraser wrote:[...]Sorry, that probably came off as a bit harsh. Everyone has one or two issues they care really strongly about (const, pure, whatever). This one's mine.
Jun 10 2008