Confused about Inner Classes

Steven Schveighoffer schveiguy at yahoo.com
Mon Oct 22 10:10:58 PDT 2007


"Janice Caron" wrote
> On 10/22/07, Bruce Adams <tortoise_74 at yeah.who.co.uk> wrote:
>>    Just to check something here. I may be having a stupid day here. Are 
>> you saying there is a pointer member available from any inner class to 
>> the outer?
>
> I believe that is the case, yes.
>
>>. But it also looks like the outer class always has at least one
> instance of the inner class.
>
> Other way round, I think. The inner class has always has exactly one
> instance of the outer class (accessible via the member "outer", or
> implicitly). The outer class, by contrast, always has exactly one
> /declaration/ of the inner class.
>
> It's definitely weird. I tried this earlier on, and it compiled. (Hope
> I'm remembering this right!)
>
> abstract class OuterA
> {
>    class Inner
>    {
>    }
> }
>
> class OuterB : OuterA
> {
>    Inner getInner()
>    {
>        return new Inner());
>    }
> }
>
> auto a = (new OuterB).getInner;
>
> This /looks/ totally weird. The class OuterB has no inner class, and
> yet it is still able to do new Inner - which is an inner class of
> OuterA. But it's allowed because OuterA is the superclass of OuterB,
> so it looks like classes inherit the inner class declarations of
> parent classes. Conversely, instances of Inner would have access to
> OuterB's variables (and therefore, OuterA's variables).

Almost :)  Since Inner doesn't yet know that OuterB exists when it was 
coded, it doesn't have access to OuterB's variables any more than a function 
in A has access to B's variables.  It does have access to virtual functions 
that A defined and B overrode.

You can look at an inner class as a class which has a context "outer" 
pointer which points to the outer class instance.  The benefit of having 
inner classes is you don't have to always reference that pointer or worry 
about passing it to the inner class on construction.  It's very similar to 
the 'this' pointer, which you don't always have to reference to access 
members of the class.

For example, the following two cases are equivalent:

class Case1
{
   int m;
   Case1Inner getInner()
   {
      return new Case1Inner(this);
   }
}

class Case1Inner
{
    Case1 context;
    this(Case1 context)
    {
        this.context = context;
    }

    int getM()
    {
        return context.m;
    }
}

....

class Case2
{
    int m;
    Case2Inner getInner()
    {
       return new Case2Inner;
    }

    class Case2Inner
    {
       int getM()
       {
           return m;
       }
    }
}

>
> And no - I haven't really got my head round it either. I'm just
> playing around, seeing what compiles and what doesn't and trying to
> grok it.

I'm not sure where the concept of inner classes started, but I first 
encountered them from Java.  They are almost a way to do 
multiple-inheritance, but not quite.  They were used in Java a lot with 
their UI library.  For example, let's say you have a class that represents a 
GUI window with a lot of buttons.  You want each button to do something 
different, and the way the button performes an action is to have an instance 
of a ButtonHandler interface, which has an activate() method.  If you define 
your class to implement the ButtonHandler interface, then the same method 
gets called for all the buttons, which is not what you want.  So you can 
define an inner class which implements ButtonHandler and does the right 
thing for each button.  You can even define them anonymously like so:

button1.setHandler(new class ButtonHandler { activate() {button1Pressed = 
true;} });

The anonymous class declared here is an inner class and so has immediate 
access to all the variables of the outer class, including button1Pressed.

hopefully this helps a little :)

-Steve 





More information about the Digitalmars-d mailing list