Доступ к конструктору из абстрактного базового класса с отражением - PullRequest
6 голосов
/ 13 января 2011

Я играюсь с отражением Java. У меня есть абстрактный класс Base с конструктором.

abstract class Base {
    public Base( String foo ) {
        // do some magic
    }
}

У меня есть еще несколько классов, расширяющих Base. Они не содержат много логики. Я хочу создать их экземпляр с помощью конструктора Base, без необходимости писать прокси-конструкторы в этих производных классах. И, конечно же, я хочу создать экземпляр этих производных классов с помощью Reflection. Скажи:

Class cls = SomeDerivedClass.class;
Constructor constr;
constr = cls.getConstructor( new Class[] { String.class } ); // will return null
Class clsBase = Base.class;
constr = clsBase.getConstructor( new Class[] { String.class } ); // ok
Base obj = (Base) constr.newInstance( new Object[] { "foo" } ); // will throw InstantiationException because it belongs to an abstract class

Есть идеи, как мне создать экземпляр производного класса с помощью конструктора Base? Или должен Я объявляю эти тупые прокси-конструкторы?

Ответы [ 4 ]

9 голосов
/ 13 января 2011

Класс не наследует конструкторов от своего родителя.У класса нет родительских конструкторов (хотя он может их вызывать). Поэтому вам нужно вызывать конструкторы, которые есть у класса, а не конструктор, который есть у суперкласса.вызывает конструктор по умолчанию для родителя по умолчанию.Если родитель не имеет конструктора по умолчанию, то и его непосредственные потомки не могут.

2 голосов
/ 13 января 2011

Вы не можете создать абстрактный класс без указания всех деталей, которые сделают его «неабстрактным».

Это означает в примере:

public abstract class Parent {
  String name;

  public Parent(String name) {
    this.name = name;
  }

  abstract public String getName();

}

никакое количество конструктора, управляющего с помощью отражения, не вернет класс Parent-only. Однако вы можете вернуть «анонимный» класс, указав абстрактные детали во время построения, например:

Parent parent = new Parent() {
    public String getName() { return "Bob"; }
  };

Помните, что подклассы также вызывают родительский конструктор, даже если вы не вводите код явно. Подкласс, написанный как:

public class Child extends Parent {
  public Child(String name) {
  }
}

будет искать конструктор без аргументов в классе Parent. Если он найдет его, он будет скомпилирован в код, эквивалентный

public class Child extends Parent {
  public Child(String name) {
    super();
  }
}

Если он не находит конструктор без аргументов в классе Parent, он не сможет скомпилироваться, пока вы явно не укажете конструкцию родительского класса с помощью вызова конструктора super(name);.

Еще одна вещь, которую нужно помнить, все классы являются подклассами Object, поэтому, если вы не предоставите extends SomeClass, например, так:

public class JustMe {
}

Компилятор концептуально "исправляет" ваш код во время компиляции так:

public class JustMe extends Object {

   public JustMe() {
     super();
   }
}

Класс Object содержит набор нативного (не Java) кода для регистрации в JVM, обеспечивающей правильную сборку мусора, управление памятью, принудительное использование типов и т. Д. В течение всего срока службы Object.

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

2 голосов
/ 13 января 2011

Боюсь, что ваши подклассы даже не скомпилируются, пока у вас не будет явного конструктора, вызывающего один из конструкторов super ().

1 голос
/ 13 января 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...