2013-02-01 2 views
6

Я очень растерялся с конструкциями Overriding Construct. Конструктор не может быть отменено, является результатом того, что я получаю, когда я искал его в гугле мой вопросПерестраивающие конструкторы

public class constructorOverridden { 

    public static void main(String args[]) { 
     Sub sub = new Sub(); 
     sub.test(); 
    } 
} 

class Super { 
    Super() { 
     System.out.println("In Super constructor"); 
     test(); 
    } 

    void test() { 
     System.out.println("In Super.test()"); 
    } 
} 

class Sub extends Super { 
    Sub() { 
     System.out.println("In Sub constructor"); 
    } 

    void test() { // overrides test() in Super 
     System.out.println("In Sub.test()"); 
    } 
} 

, когда я запускаю это я получил результат как

In Super constructor 
In Sub.test() 
In Sub constructor 
In Sub.test() 

пожалуйста, обратите внимание на метод испытания в подклассе выполняется. Это показывает, что конструктор Суперкласса переопределен. Правильно ли это?

ответ

19

Конструкторы не являются полиморфными - вы не переопределите их вообще. Вы создаете конструкторы new в подклассе, и каждый конструктор подкласса должен цепляться (возможно, косвенно) к конструктору суперкласса. Если вы явно не привязаны к конструктору, неявный вызов конструктора безразмерного суперкласса вставлен в начало тела конструктора подкласса.

Теперь с точки зрения переопределения методов - объект имеет свой «конечный тип» с самого начала, в том числе при выполнении конструктора суперкласса. Поэтому, если вы напечатаете getClass() в коде конструктора Super, в выводе вы увидите Sub. Результатом этого является переопределенный метод (т. Е. Sub.test), хотя конструктор Sub еще не выполнен.

Это принципиально плохая идея, и вы почти всегда должны избегать вызова потенциально переопределены методы в конструкторах - или документ очень четко, что это будет так (так что код подкласса знает, что он может» t полагаться на переменные, которые были инициализированы соответственно и т. д.).

+0

Затем, какой подход следует использовать, избегая «вызова переопределенных методов в конструкторах»? То, что я пытаюсь выполнить, - это базовый поток в суперклассическом конструкторе, вызывающий абстрактные методы init(), build(), затем fill(). Таким образом, все подкласс должны пройти один и тот же поток! – Akshat

+0

@Akshat: Ну, похоже, что это относится к категории «документ очень четко». Обычно есть несколько способов разработки вокруг этого, но трудно дать общий рецепт. –

+0

Если бы вы могли просто дать ссылку на эти способы, это было бы здорово! – Akshat

3

Первая неявная строка конструктора - это вызов Super(). Вот почему вы получаете эти результаты.

3

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

В приведенном выше примере конструктор суперкласса вызывает переопределенный метод (test()). Это работает, но потенциально опасно, поскольку конструктор подкласса не был вызван, и ваш подкласс не будет полностью инициализирован. По этой причине вызов переопределенных (или переопределяемых) методов в конструкторе не является хорошей практикой.

2

Это не переопределяющий конструктор и конструктор суперкласса нельзя переопределить, он может быть перегружен.

Когда вы создадите объект класса суперкласса класса, будет создан экземпляр сначала, тогда будет создан экземпляр подкласса. Его как Ребенок не может существовать без родителя.

Компилятор автоматически вызовет конструктор суперкласса из конструктора подкласса.

Sub() { 
    super(); 
    System.out.println("In Sub constructor"); 
} 
4

Вы не можете переопределить конструктор, поскольку конструктор вызывается именем класса, который он строит. Как вы можете создать несколько разных классов с одним и тем же конструктором? Кроме того, дочерний класс не наследует конструкторы от своего родителя.

Если родительский конструктор выполняет некоторые важные инициализации, он может быть вызван из детского конструктора, используя супер: конструктор класса

class Err extends Throwable { 
    Err(String message) { 
     super(message); // Call the constructor of Throwable. 
     .. 

Родителя также всегда называется. Если вы сами не вызываете никаких, конструктор без параметров вызывается автоматически перед вводом конструктора производного класса. Если у родителя нет конструктора без параметров и вы его не вызываете, сообщается об ошибке времени компиляции.

Смежные вопросы