#java
Доброго времени суток всем. Читая книгу Брюса Эккеля, натолкнулся на следующий текст: Конечно, очень важно, чтобы подобъект базового класса был правильно инициализирован, и гарантировать это можно только одним способом: выполнить инициализацию в конструкторе, вызывая при этом конструктор базового класса, у которого есть необходимые знания и привилегии для проведения инициализации базового класса. Java автоматически вставляет вызовы конструктора базового класса в конструктор производного класса. Помогите разобраться, почему же так важно вызвать конструктор базового класса для класса наследника? И что будет если это не произойдёт (теоретически)? Спасибо.
Ответы
Ответ 1
Базовый класс по сути является как-бы частью наследника. Поэтому, если он не будет проинициализирован, то работать ничего не будет. Пример: public class A { protected int valA = 1; } public class B extends A { protected int valB = 2; public int getVal(){ return valB + valA; } } Наследование позволяет писать такую конструкцию. Если родительский класс не будет инициализировн, то в строке return valB + valA; будет неизвестно значение valA. Насколько я понимаю, не может быть ситуации, когда конструктор базового класса не вызовется (поправьте меня, если я ошибаюсь). Пример автоматического вызова конструкторов базовых классов.Ответ 2
Это действительно важно. И вот почему. У базового класса может быть (и весьма часто бывает) какое-то внутренне состояние, которое нужно правильно инициализировать. И если этого не сделать, то ваш класс скорее всего не сможет правильно работать. Простой пример (код может содержать синтаксические ошибки - пишу без компилятора. Но суть, думаю, будет понятна): class Base { public Base(int size) { _someData = new int[size]; } protected int[] _someData; } class Child extends Base { public Child(int size) { // super(size); } void doSomething(int index, int value) { /// ... _someData[index] = value; } } Допустим, вы в конструкторе Child не вызвали конструктор предка Base. И тогда при вызове метода doSomething вы получите исключение, так как поле _someData не было инициализировано, так как его инициализация происходит в конструкторе предка, который вы не вызывали. Таких примеров, в том числе и куда более сложных, может быть очень много. К тому же ситуация может усугубляться, если вы создаете класс-наследник от класса, исходников которого у вас нет. Тогда вы вообще не можете знать, какие проблемы могут случиться с "недоинициализированным" классом до тех пор, пока с этими проблемами не столкнетесьОтвет 3
В общем то в цитате из Эккеля и так все достаточно подробно написано. Класс-наследник только расширяет (дополняет) или изменяет функционал класса-родителя и не является самостоятельным классом, соответственно для работы класса-наследника необходимы инициализицации, производимые в базовом классе. Если этого не сделать, то вы получите различного вида экзепшены, указывающие на то, что именно не проинициализировано. Так же, если базовый класс не производит никакой инициализации и прочих действий, на которые опирается класс-наследник, то вызов его в конструкторе не требуется.Ответ 4
Практически, если вы попытаетесь каким-то образом исключить вызов конструктора родительского класса, то компилятор сообщит об ошибке. Теоретически это означает, что у вас не будет корректно создан объект дочернего класса, потому что та часть объекта или некоторая функциональность, которая относится к родительскому подобъекту, не будет инициализирована или выполнена, и поведение программы будет неопределенным. Например, родительский объект может иметь private данные, которые кроме него самого никто инициализировать не может. Или родительский объект при своем конструировании может выделять и запрашивать какие-нибудь ресурсы, как, например, открытие файла или базы данных, установление соединения в сети, установка различных системных флагов и т.д.Ответ 5
Хотелось бы расстроить людей которые вдруг посчитали в 2015 году что они разрешили этот вопрос. Мы можем взять и инициализировать поля если они конечно публичные в конструкторе производного и тогда вызов базового вроде как не нужен, но хохма вся в том что конструкторы срабатыват в порядке выведения классов от базового к конструктору класса объект которого мы создаём и всё это дело за нас делает компилятор если мы не создавали конструкторов с параметрами, в противном случаи всё это делать надо нам дабы не нарушать установленный не нами порядок, а вопрос почему это уже проще взять и застрелиться чем сидеть и думать почему. Это вопрос из разряда что было раньше курица, или яйцо. P.S да можно для себя принять такое объяснение что поля в базовом классе private и потому доступ есть только у конструктора базового класса и тогда необходимость налицо, также можно обосновать это тем что основная идея наследования состоит в том чтобы писать меньше кода и повторно использовать уже написанный.
Комментариев нет:
Отправить комментарий