Thread overview
Is this a D puzzler or a bug?
Mar 30, 2007
Bradley Smith
Mar 30, 2007
Bradley Smith
Apr 01, 2007
janderson
Mar 30, 2007
BCS
Mar 31, 2007
Bradley Smith
March 30, 2007
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.

March 30, 2007
"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.


March 30, 2007
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.

March 30, 2007
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.


March 31, 2007
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
March 31, 2007
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.
March 31, 2007
"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?


March 31, 2007
"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.


April 01, 2007
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.