June 09, 2005
This kind of borders on a bug and a questionable implementation issue, but it's certainly not good.

class A
{
 this()
 {
  b=new B;
 }

 class B
 {
  int x() { return 5; }
 }

 B b;
}

class C : A
{
 this()
 {
  b=new B;
  // b2=new A.B;  // This is illegal for some reason -- "no 'this' for
nested class B" ??
 }

 class B
 {
  int x()
  {
   // Next line causes a stack overflow from recursion, but I want to call
the A.B's x(), but it's
   // not available as the C.B hides the A.B
   // return b.x+10;
   return 10;
  }
 }

 // Another b?!  But this is of type C.B, not A.B.  This overrides the A.B
member, however,
 // and if I make this member, I can't access the A.B member anymore.
 B b;
 A.B b2;  // This is legal, however
}

void main()
{
 A a=new A;
 C c=new C;
 writefln(a.b.x); // 5
 writefln(c.b.x); // 10
 a=c;
 // This is somewhat confusing - when you upcast, there is still a "b"
member, so it still
 // works, but returns something different.
 writefln(a.b.x); // 5
}

This shows a few problems:

1) class A has a class B, and so does C.  They are different classes, however, named A.B and C.B.  But note that although C inherits from A, I am allowed to have another member named b.

I'm not sure if this behavior was allowed before, but it seems legal to have members in derived classes which override members in super classes.  This makes sense for functions, but not really for regular members.

2) Because C's b overrides A's b, I can no longer access the A.B b member in C.  Thus, the commented-out return statement in C.B.x causes a stack overflow from infinite recursion.  There is no way for me to specify "super.b.x" or anything like that, as the "super" of C.B is Object.

3) I can declare an A.B member b2, but I can't initialize it.  If I try to use "new A.B," I get the cryptic error message "no 'this' for nested class B."  Weirder - I can actually make a member called "A.B b," which overrides the "b" member in A in both name and type.

4) In main(), I create an A and a C.  a.b.x returns 5 and c.b.x returns 10, as expected.  But if I cast the C to an A, it then returns 5.  This again stems from the name overriding issue - both A and C have a "b" member, but they have different properties.  Confusing.

Again, I'm not sure which of these qualify as bugs, but they certainly are foggy areas of the nested class spec.