Java Inner Class extends Outer Class
Asked Answered
C

3

14

There are some cases in Java where an inner class extends an outer class.

For example, java.awt.geom.Arc2D.Float is an inner class of java.awt.geom.Arc2D, and also extends Arc2D. (c.f. http://download.oracle.com/javase/6/docs/api/java/awt/geom/Arc2D.Float.html)

Also, sun.org.mozilla.javascript.internal.FunctionNode.Jump extends sun.org.mozilla.javascript.internal.Node, which is a superclass of FunctionNode. (sorry... cannot find a link to the javadoc)

To me, this seems odd. Could you then create these?

new Arc2D.Float.Float() //n.b. I couldn't get this to compile in Intellij IDEA;

new FunctionNode.Jump.Jump.Jump(1); // I could get this to compile

What purpose does it serve to have a subclass nested as an inner class of the superclass?

I wondered whether it was to access something in the superclass, but if you wanted to access any variables/methods in the parent, you could use

super.variable;

or

super.method();

Edit 1: jjnguy has suggested it's to keep the logic in the same place. In which case, why wouldn't you write a file com.mypackage.AbstractTest:

abstract class AbstractTest {
  abstract String getString();
}

class ExtensionTest extends AbstractTest {
  @Override
  String getString() {
    return "hello world";
  }
}

... rather than:

abstract class AbstractTest {
  abstract String getString();

  class ExtensionTest extends AbstractTest {
    @Override
    String getString() {
      return "hello world";
    }
  }
}

Edit 2: It has rightly been pointed out that the suggestion in my previous edit was flawed, as couldn't construct ExtensionTest outside of the package. However, I've had a further think about this over the weekend, so what about the following:

abstract class Test {
  public class ExtensionTest extends AbstractTest {
    @Override
    String getString() {
      return "hello world";
    }
  }

  private abstract class AbstractTest {
    abstract String getString();
  }
} 

In essence, the best answer I've seen so far is that having an inner class extend its outer class allows the logic to be grouped together. However, I think that this can be done without the extension.

In my mind, it seems like bad design to have a class that can have an infinite number of the same subclasses nested within it. (Context: this came up whilst trying to produce a dictionary for a code completion utility, and threw a StackOverflowException. I found a workaround, but I just cannot understand why it had been designed that way.)

Coping answered 19/8, 2011 at 17:26 Comment(1)
@jinguy has posted a good answer for the why. As for your example, javac will happily compile the line Object obj3 = new java.awt.geom.Arc2D.Float.Float.Float ();.Tymon
F
16

Have a look at Java's Point2D. It has two inner classes that are sub-classes of it.

The important thing to note is that they are static inner classes. This has an entirely diffenent meaning that a regular inner class. Just like a static method, a static class is defined at the class-level instead of the object level.

In the Point2D case, it is done to logically couple the classes and their logic. It helps a user of the abstract type Point2D find an implementation that they can use.

In response to your edit I'd like to point out 1 important fact. A single Java file may only contain one public class, except for public inner classes. While both of your examples may compile, they do not allow access to those classes to the public. If you want to present multiple public classes to someone in a single file, you must use public static inner classes.

Flutist answered 19/8, 2011 at 17:30 Comment(12)
I can see your reasoning, but I think there are better ways of doing this... see my edit to the question.Coping
@amaid, See my last paragraph I added.Flutist
If you want to present multiple public classes... in a single file that's exactly the reason why I sometimes do stuff like that. BTW that someone could be myself - just keeping classes "packaged" in single file for my own convenience.Conduit
@Conduit (and jjinguy) - I've edited my post and would appreciate your thoughts.Coping
@amaid, in you second edit I cannot think of a reason to do that. An inner abstract class that only the enclosing class can extend seems useless to me. I don't think it's good practice.Flutist
Ok - so you could make the inner abstract class public, but that's kind of by the by...Coping
@amaid, there are very few cases when you would want an interface or abstract class that only one class could ever implement, in fact I can't think of any situations where that would be a good idea. I also can't imagine a scenario where it would be better to make an inner class abstract. It just seems like the wrong way to go about something.Flutist
@Coping currently your inner classes aren't declared static (note Arc2D.Float is static). To me, this makes a world of difference and basically ruins each and every benefit that I could ever imagine. If you're going to discuss named inner classes that aren't declared static, then my only advice for this would be to avoid it like a plague. Static named inner classes are OK in my book, non-static ones are nothing but total disasterConduit
@Conduit & jjnguy - this isn't really answering my question. My question is why would you want an inner class to extend its outer class. The best answer I've heard so far was from jjnguy, which was to keep the logic together. I'm suggesting there are other ways to do that without an inner class extending an outer class... so why would you have an inner class extend an outer class? (Whether the inner class is static or not is beside the point...)Coping
@amaid, "why would you want an inner class to extend its outer class" - You wouldn't. That's what I was trying to get across in my other comments.Flutist
great - that's what I thoughtCoping
I dont think Java supports static inner classes. However it does static nested classes.Lubberly
E
10

There are two cases of inner-classes:

  • static inner-classes. The inner-class does not keep reference to the outer-class.

  • non-static inner-classes. The inner-class does keep a reference to the outer-class.

The case of a static inner-class that extends the outer-class is not as interesting as the non-static inner-class extending the outer-class.

What happens with the latter is: to create the inner-class, one needs a reference to the outer-class. However, as the inner-class is an instance of the outer-class, it also accepts a reference to another instance of the inner-class, to be used as outer-class.

Let's look at some code:

Outer a = new Outer();
Outer.Inner b = a.new Inner();

// Only possible when Inner extends Outer:
Outer.Inner c = a.new Inner().new Inner();

If you know the builder pattern, this can be used to have an OOP-version of it:

public abstract class Command {

    // Not possible to create the command, else than from this file!
    private Command() {
    }

    public abstract void perform();

    public static class StartComputer extends Command {
        public void perform() {
            System.out.println("Starting Computer");
        }
    }

    public class OpenNotepad extends Command {
        public void perform() {
            Command.this.perform();
            System.out.println("Opening Notepad");
        }
    }

    public class ShutdownComputer extends Command {
        public void perform() {
            Command.this.perform();
            System.out.println("Shutting Computer");
        }
    }

}

Which is used as: new Command.StartComputer().new OpenNotepad().new ShutdownComputer().perform();.

Edla answered 19/8, 2011 at 17:45 Comment(5)
Do you think that example is good style? That looks terrible.Flutist
I agree! It looks terrible and requires some getting-used-to-time.Edla
I've never seen that used before. Is this common practice in some places?Flutist
Wow, this looks so strange but I like it. You could also use decorator pattern so your code would look like new Command.StartComputer(new Command.OpenNotepad(new Command.ShutdownComputer()))).perform(). But with your code you have to start from StartComputer. How did you find this solution?Leukorrhea
or just do the normal thing and have your methods return the type they're in, so you get the syntax without the new keyword and less instantiationMerc
H
2

There 1st one compiles fine on my IntelliJ.

Strictly speaking, static member classes are not inner classes. They are called nested classes.

Hinayana answered 19/8, 2011 at 17:45 Comment(1)
static nested classes is more accurate. According to docs.oracle.com/javase/tutorial/java/javaOO/nested.html Nested classes that are declared static are called static nested classes. Non-static nested classes are called inner classes.Bacterin

© 2022 - 2024 — McMap. All rights reserved.