www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is this a D puzzler or a bug?

reply Bradley Smith <digitalmars-com baysmith.com> writes:
What is wrong with the following code?

class A {
   protected void method() {}
}

class B : public A {
   protected void method() {
     A.method();
   }
}

Answer:

If A and B are defined in the same module, A is able to access the 
non-static protected method of its superclass using a static method call.

However, if A and B are defined in different modules, the error "class 
a.A member method is not accessible" occurs.

Is this a bug? (I don't know. I am really asking.)


Current solution:

Replacing "A.method()" with "super.method()" corrects the problem.
Mar 30 2007
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Bradley Smith" <digitalmars-com baysmith.com> wrote in message 
news:eujsku$2njp$1 digitalmars.com...
 What is wrong with the following code?

 class A {
   protected void method() {}
 }

 class B : public A {
   protected void method() {
     A.method();
   }
 }

 Answer:

 If A and B are defined in the same module, A is able to access the 
 non-static protected method of its superclass using a static method call.

 However, if A and B are defined in different modules, the error "class a.A 
 member method is not accessible" occurs.

 Is this a bug? (I don't know. I am really asking.)

This is "the way C++ does it" and therefore the way D should do it as well. It also means that B can't access any protected members of A references. Stupid, I know, and it's never going to change as long as Walter is in charge.
 Current solution:

 Replacing "A.method()" with "super.method()" corrects the problem.

That's really how you're "supposed" to do it. It's also a little nicer-looking, since it's obvious you're calling the base class's implementation of the method.
Mar 30 2007
next sibling parent Bradley Smith <digitalmars-com baysmith.com> writes:
Jarrett Billingsley wrote:
 "Bradley Smith" <digitalmars-com baysmith.com> wrote in message 
 news:eujsku$2njp$1 digitalmars.com...
 What is wrong with the following code?

 class A {
   protected void method() {}
 }

 class B : public A {
   protected void method() {
     A.method();
   }
 }

 Answer:

 If A and B are defined in the same module, A is able to access the 
 non-static protected method of its superclass using a static method call.

 However, if A and B are defined in different modules, the error "class a.A 
 member method is not accessible" occurs.

 Is this a bug? (I don't know. I am really asking.)

This is "the way C++ does it" and therefore the way D should do it as well. It also means that B can't access any protected members of A references. Stupid, I know, and it's never going to change as long as Walter is in charge.

I don't understand what you mean by "This is the way C++ does it". The following equivalent C++ code is perfectly fine. class A { protected: void method() {} }; class B : public A { protected: void method() { A::method(); } }; To me, this indicates that D is *not* doing it the way C++ does it.
Mar 30 2007
prev sibling parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Jarrett Billingsley wrote:
 "Bradley Smith" <digitalmars-com baysmith.com> wrote in message 
 news:eujsku$2njp$1 digitalmars.com...
 What is wrong with the following code?

 class A {
   protected void method() {}
 }

 class B : public A {
   protected void method() {
     A.method();
   }
 }

 Answer:

 If A and B are defined in the same module, A is able to access the 
 non-static protected method of its superclass using a static method call.

 However, if A and B are defined in different modules, the error "class a.A 
 member method is not accessible" occurs.

 Is this a bug? (I don't know. I am really asking.)

This is "the way C++ does it" and therefore the way D should do it as well. It also means that B can't access any protected members of A references. Stupid, I know, and it's never going to change as long as Walter is in charge.
 Current solution:

 Replacing "A.method()" with "super.method()" corrects the problem.

That's really how you're "supposed" to do it. It's also a little nicer-looking, since it's obvious you're calling the base class's implementation of the method.

In trying to figure out an idea to put forward on how me might be able to call super-class definitions directly (since the problem I see with super.method() is that you can't selectively invoke a specific ancestor, only your direct parent) I had the sudden cute thought about how it can be done in MiniD (untested). (Granted MiniD doesn't have protection/visibility attributes, plus both inheritance and instantiation behave differently from D, so its moot in that context, but the idea stands conceptually.) class A { function method () {} } class B : A { function method () { method(with this as A); // Its cute how existing syntax can read sometimes. } } Thinking from here, the D equivelant would, I suppose, be this... class A { protected void method () {} } class B : A { override protected void method () { (cast(A) this).method(); } } And once again the upcoming macros feature could help out some. I'm guessing at exactly what the macro syntax will be, in that I'm unsure they will have tuples like what I'm using here. macro MUpCall (Ancestor, Method, Args ...) { (cast(Ancestor) this).method(Args); } class A { protected void method (int i) {} } class B : A { override protected void method (int i) { MUpCall(A, method, i); } } -- Chris Nicholson-Sauls
Mar 29 2007
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Chris Nicholson-Sauls" <ibisbasenji gmail.com> wrote in message 
news:eukaln$h4q$1 digitalmars.com...
 In trying to figure out an idea to put forward on how me might be able to 
 call super-class definitions directly (since the problem I see with 
 super.method() is that you can't selectively invoke a specific ancestor, 
 only your direct parent) I had the sudden cute thought about how it can be 
 done in MiniD (untested).  (Granted MiniD doesn't have 
 protection/visibility attributes, plus both inheritance and instantiation 
 behave differently from D, so its moot in that context, but the idea 
 stands conceptually.)

 class A {
   function method () {}
 }

 class B : A {
   function method () {
     method(with this as A); // Its cute how existing syntax can read 
 sometimes.
   }
 }

Nice shot (and very cute), but unfortunately because of the way global lookup works in MiniD, when you call "method(with this as A)" inside B's method(), it looks "method" up (and finds it) in 'this' first, calls itself, and so goes into infinite recursion. Though you have just made me realize that there doesn't seem to be a way to call the base class's implementation of a method, directly or indirectly, in MiniD..!
 Thinking from here, the D equivelant would, I suppose, be this...

 class A {
   protected void method () {}
 }

 class B : A {
   override protected void method () {
     (cast(A) this).method();
   }
 }

If declared in separate files, this doesn't work. If in the same file, this causes infinite recursion for much the same reasons as the MiniD code -- the method is looked up polymorphically, and so even though you're upcasting "this" to an A, it still calls the B implementation of method, and so it loops. One thing that seems like it should work is: typeof(super).method(); This compiles even if the classes are in separate files (while A.method() fails), but gives infinite recursion again. Looking in the specs, it seems the "non-virtual call" meaning is only applied to the "typeof(this).method()" form, so doing "typeof(super).method()" still does a virtual call. And of course again, this only allows you to call direct ancestors. But then, how often do you need to call the implementation of a method more than one level up?
Mar 30 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:eukglm$mfk$1 digitalmars.com...
 Though you have just made me realize that there doesn't seem to be a way 
 to call the base class's implementation of a method, directly or 
 indirectly, in MiniD..!

I take that back. Given that B derives from A, it can call A's implementation of a method by writing: A.method(with this); but it's a bit clumsy. Although this _does_ allow for calling method implementations several levels up in the inheritance graph.
Mar 30 2007
prev sibling parent janderson <askme me.com> writes:
Chris Nicholson-Sauls wrote:
 Jarrett Billingsley wrote:
 "Bradley Smith" <digitalmars-com baysmith.com> wrote in message 
 news:eujsku$2njp$1 digitalmars.com...
 What is wrong with the following code?

 class A {
   protected void method() {}
 }

 class B : public A {
   protected void method() {
     A.method();
   }
 }

 Answer:

 If A and B are defined in the same module, A is able to access the 
 non-static protected method of its superclass using a static method 
 call.

 However, if A and B are defined in different modules, the error 
 "class a.A member method is not accessible" occurs.

 Is this a bug? (I don't know. I am really asking.)

This is "the way C++ does it" and therefore the way D should do it as well. It also means that B can't access any protected members of A references. Stupid, I know, and it's never going to change as long as Walter is in charge.
 Current solution:

 Replacing "A.method()" with "super.method()" corrects the problem.

That's really how you're "supposed" to do it. It's also a little nicer-looking, since it's obvious you're calling the base class's implementation of the method.

In trying to figure out an idea to put forward on how me might be able to call super-class definitions directly (since the problem I see with super.method() is that you can't selectively invoke a specific ancestor, only your direct parent) I had the sudden cute thought about how it can be done in MiniD (untested). (Granted MiniD doesn't have protection/visibility attributes, plus both inheritance and instantiation behave differently from D, so its moot in that context, but the idea stands conceptually.) class A { function method () {} } class B : A { function method () { method(with this as A); // Its cute how existing syntax can read sometimes. } } Thinking from here, the D equivelant would, I suppose, be this... class A { protected void method () {} } class B : A { override protected void method () { (cast(A) this).method(); } } And once again the upcoming macros feature could help out some. I'm guessing at exactly what the macro syntax will be, in that I'm unsure they will have tuples like what I'm using here. macro MUpCall (Ancestor, Method, Args ...) { (cast(Ancestor) this).method(Args); } class A { protected void method (int i) {} } class B : A { override protected void method (int i) { MUpCall(A, method, i); } } -- Chris Nicholson-Sauls

This will, as mentioned cause infinit recursion. Here's a syntax suggestion. What about? super.super.method(); It also would be nice if we could do things like: A.super.method(); //Parent of A This would help avoid issues when you insert a new class inheritance between A and B. Although I'm not sure how common that would be.
Apr 01 2007
prev sibling parent reply BCS <ao pathlink.com> writes:
Reply to Bradley,

 What is wrong with the following code?
 
 class A {
 protected void method() {}
 }
 class B : public A {
 protected void method() {
 A.method();
 }
 }
 Answer:
 
 If A and B are defined in the same module, A is able to access the
 non-static protected method of its superclass using a static method
 call.
 
 However, if A and B are defined in different modules, the error "class
 a.A member method is not accessible" occurs.
 
 Is this a bug? (I don't know. I am really asking.)
 
 Current solution:
 
 Replacing "A.method()" with "super.method()" corrects the problem.
 

I think the issue is that in D everything in a given module has implicit private access to everything else in that module. I'm not quite sure what you are looking for, but this distinction generally play into things that change when things move from one module to another.
Mar 30 2007
parent Bradley Smith <digitalmars-com baysmith.com> writes:
BCS wrote:
 Reply to Bradley,
 
 What is wrong with the following code?

 class A {
 protected void method() {}
 }
 class B : public A {
 protected void method() {
 A.method();
 }
 }
 Answer:

 If A and B are defined in the same module, A is able to access the
 non-static protected method of its superclass using a static method
 call.

 However, if A and B are defined in different modules, the error "class
 a.A member method is not accessible" occurs.

 Is this a bug? (I don't know. I am really asking.)

 Current solution:

 Replacing "A.method()" with "super.method()" corrects the problem.

I think the issue is that in D everything in a given module has implicit private access to everything else in that module. I'm not quite sure what you are looking for, but this distinction generally play into things that change when things move from one module to another.

I was looking for a way to call a specific superclass method from an overridden method. I wasn't expecting that access to a non-static method through a static call would have different protection than specified on the non-static method.
Mar 30 2007