4

I am learning inner and outer classes in Java. I know what inner and outer classes are and why they are used. I came across the following question on this topic and could not find an answer.

Suppose the following code is given:

class outer{
    class inner{

    }
}

class SubClass extends outer.inner{
}

Question: How should the minimal subclass constructor be defined? and why?

Option 1-
Subclass () {
    //reason: bacause the default constructor must always be provided
}
Option 2-
Subclass (Outer outer) {
    //reason : because creating an instance of **Subclass** requires an instance 
    //of outer, which the **Subclass** instance will be bound to
}

Option 3-
Subclass (Outer outer) {
    outer.super();
    //reason : because creating an instance of **Subclass** requires an explicit 
    //call to the **Outer's** constructor, in order to have an enclosing instance 
    //of **Outer** in scope.
}
Option 4- 
Subclass (Outer.inner inner) {
    //reason : bacause an instance of **inner** is necessary so that there is a 
    //source to copy the derived properties from
}

PS. This is a multiple choice question. Only 1 answer is expected

i am new to java and don't know much about these advanced topics

Thanks

Awais Fayyaz
  • 2,275
  • 1
  • 22
  • 45
  • I believe none of the above, and that this is a case for a [Receiver Parameter - JLS #8.4.1](http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.1). – user207421 Jul 18 '17 at 12:26

2 Answers2

2

Here is an example from the JLS that follow this same logic but by not passing the enclosing instance but by creating it directly in the constructor :

Example 8.8.7.1-1. Qualified Superclass Constructor Invocation

class Outer {
    class Inner {}
}
class ChildOfInner extends Outer.Inner {
    ChildOfInner() { (new Outer()).super(); }
}

Superclass constructor invocations may be subdivided:

  • Unqualified superclass constructor invocations begin with the keyword super (possibly prefaced with explicit type arguments).

  • Qualified superclass constructor invocations begin with a Primary expression.

They allow a subclass constructor to explicitly specify the newly created object's immediately enclosing instance with respect to the direct superclass (§8.1.3). This may be necessary when the superclass is an inner class.

The case the nearest in proposed answers is

public SubClass(Outer outer) {
    outer.super();
}

To extend Outer.Inner that is an inner class of Outer, SubClass constructor needs to have an instance of Outer that is the enclosing type.

outer.super(); will invoke the constructor of the Outer parent class that is the Inner constructor.

The outer.super(); syntax may be disconcerting as we don't invoke generally super() on a parameter of a constructor but in the case of a class extending a inner class, the constructor of the subclass allows this syntax.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • Does your class `Outer` have a method named `super()`? Unless it does, `super` is a reserved word (a language construct) that is reserved to the calling of the superclass' constructor, and as such it cannot be qualifyed with class or instance identifier... – Usagi Miyamoto Jul 18 '17 at 12:29
  • If it compiles, then look at the bytecode, and tell me: does it run before, or after the (implicit) super constructor call? – Usagi Miyamoto Jul 18 '17 at 12:30
  • You downvote without any good reason. You say that it will not compile, then you change your mind and then you change still your argument. Please don't be so aggressive. – davidxxx Jul 18 '17 at 12:36
  • @Usagi Miyamoto The super constructor is invoked as last JVM statement : `invokespecial #14 // Method Outer$inner."":(L/Outer;)V` – davidxxx Jul 18 '17 at 13:26
  • @davidxxx. what could be the possible application of this type of code ? any hints ? – Awais Fayyaz Jul 19 '17 at 08:00
  • A use case of it ? With too generic class names, it may be harder to imagine it but with concrete example, it makes easily sense. Suppose a `Mother` class that has an inner class `Baby` : `class Mother { class Baby {} }`. Suppose now that you want to create a `BabyWithSuperPowers` class that extends Baby. This code makes sense : `class BabyWithSuperPowers extends Mother.Baby { BabyWithSuperPowers() { (new Mother()).super(); } }` – davidxxx Jul 19 '17 at 08:28
  • @davidxxx. regarding your mother and baby example, Mother is the main parent class, why are we invoking constructor of Parent of Mother class ( new Mother().super) ) ? Is it the hard coded construct. that we have to follow or something else ? – Awais Fayyaz Jul 20 '17 at 06:33
  • @Awais Fayyaz Sorry I have just read the message when you accepted. Because an instance of an inner class cannot be instantiated if it is not associated to an instance of the outer class. – davidxxx Jul 24 '17 at 11:42
0

I do not think, that a "outer" class can extend an inner class. That construct would mean, a class could access private members of another classes.

You could have an inner class that extends another inner class of the same outer class, though.

As for the constructors, the outer instance is specified in the instantiation, not as an argument:

class Outer {
   class Inner {
      ...
   }
   class SubInner {
      ...
   }
   void method() {
      Inner i = this.new SubInner();
   }
}
Usagi Miyamoto
  • 6,196
  • 1
  • 19
  • 33