Внутренний класс Java расширяет внешний класс - PullRequest
10 голосов
/ 19 августа 2011

В некоторых случаях в Java внутренний класс расширяет внешний класс.

Например, java.awt.geom.Arc2D.Float является внутренним классом java.awt.geom.Arc2D, итакже расширяет Arc2D.(cf http://download.oracle.com/javase/6/docs/api/java/awt/geom/Arc2D.Float.html)

Кроме того, sun.org.mozilla.javascript.internal.FunctionNode.Jump расширяет sun.org.mozilla.javascript.internal.Node, который является суперклассом FunctionNode. (извините ..не могу найти ссылку на javadoc)

Мне кажется, это странно. Не могли бы вы тогда создать их?

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

Какую цель имеет подкласс, вложенный как внутреннийкласс суперкласса?

Мне было интересно, должен ли он получить доступ к чему-либо в суперклассе, но если вы хотите получить доступ к каким-либо переменным / методам в родительском объекте, вы можете использовать

super.variable;

или

super.method();

Редактировать 1: jjnguy предложил сохранить логику в одном месте. В таком случае, почему бы вам не написать файл com.mypackage.AbstractTest:

abstract class AbstractTest {
  abstract String getString();
}

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

... вместо:

abstract class AbstractTest {
  abstract String getString();

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

Правка 2: Правильно было указано, что предложение в моем предыдущем редактировании было ошибочным, так как не могло создать ExtensionTest вне пакета. Однако яеще раз подумал об этом на выходныхтак что насчёт следующего:

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

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

По сути, лучший ответ, который я видел до сих пор, состоит в том, что наличие внутреннего класса расширяет его внешний класс, позволяя сгруппировать логику.Тем не менее, я думаю, что это можно сделать без расширения.

На мой взгляд, кажется плохим дизайном иметь класс, который может иметь бесконечное число одинаковых подклассов, вложенных в него.(Контекст: это возникло при попытке создать словарь для утилиты завершения кода и вызвало исключение StackOverflowException. Я нашел обходной путь, но я просто не могу понять, почему он был разработан таким образом.)

Ответы [ 3 ]

12 голосов
/ 19 августа 2011

Посмотрите на Java Point2D. У него есть два внутренних класса, которые являются его подклассами.

Важно отметить, что они являются static внутренними классами. Это имеет совершенно другое значение, что регулярный внутренний класс. Как и статический метод, статический класс определяется на уровне класса, а не на уровне объекта.

В случае Point2D это делается для логического соединения классов и их логики. Это помогает пользователю типа abstract Point2D найти реализацию, которую он может использовать.

В ответ на ваши изменения я хотел бы указать на один важный факт. Один файл Java может содержать только один открытый класс, , за исключением для открытых внутренних классов. Хотя оба ваших примера могут компилироваться, они не разрешают доступ к этим классам для всех. Если вы хотите представить несколько открытых классов кому-то в одном файле, вы должны использовать открытые статические внутренние классы.

7 голосов
/ 19 августа 2011

Существует два случая внутренних классов:

  • статические внутренние классы.Внутренний класс не сохраняет ссылку на внешний класс.

  • нестатический inner-классы.Внутренний класс действительно сохраняет ссылку на внешний класс.

Случай статического внутреннего класса, расширяющего внешний класс, не столь интересенкак нестатический внутренний класс, расширяющий внешний класс.

Что происходит с последним: для создания внутреннего класса требуется ссылка на внешний класс.Однако, поскольку внутренний класс является экземпляром внешнего класса, он также принимает ссылку на другой экземпляр внутреннего класса, который будет использоваться в качестве внешнего класса.

Давайте рассмотрим некоторый код:

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

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

Если вам известен шаблон компоновки , его можно использовать для получения его ООП-версии:

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");
        }
    }

}

, который используется как: new Command.StartComputer().new OpenNotepad().new ShutdownComputer().perform();.

2 голосов
/ 19 августа 2011

Там 1-й прекрасно компилируется на моем IntelliJ.

Строго говоря, статические классы-члены не являются внутренними классами.Они называются вложенными классами.

...