Вложенные внутренние классы
Объект внутреннего класса не может существовать без объекта «внешнего» класса.
Это логично: для того мы и сделали Seat и HandleBar внутренними классами, чтобы в нашей программе не появлялись то тут, то там бесхозные рули и сиденья.
Этот код не скомпилируется:
Из этого вытекает следующая важная особенность:
У объекта внутреннего класса есть доступ к переменным «внешнего» класса.
Для примера давай добавим в наш класс Bicycle переменную int seatPostDiameter — диаметр подседельного штыря.
Тогда во внутреннем классе Seat мы можем создать метод getSeatParam() , который сообщит нам параметр сиденья:
Вывод в консоль:
Обрати внимание: новая переменная объявлена с самым строгим модификатором — private . И все равно у внутреннего класса есть доступ!
Объект внутреннего класса нельзя создать в статическом методе «внешнего» класса.
Это объясняется особенностями устройства внутренних классов. У внутреннего класса могут быть конструкторы с параметрами или только конструктор по умолчанию. Но независимо от этого, когда мы создаем объект внутреннего класса, в него незаметно передается ссылка на объект «внешнего» класса. Ведь наличие такого объекта — обязательное условие. Иначе мы не сможем создавать объекты внутреннего класса.
Но если метод внешнего класса статический, значит, объект внешнего класса может вообще не существовать! А значит, логика работы внутреннего класса будет нарушена. В такой ситуации компилятор выбросит ошибку:
Внутренний класс не может содержать статические переменные и методы.
Логика здесь та же: статические методы и переменные могут существовать и вызваться даже при отсутствии объекта.
Но без объекта «внешнего» класса доступа к внутреннему классу у нас не будет.
Явное противоречие! Поэтому наличие статических переменных и методов во внутренних классах запрещено.
Компилятор выбросит ошибку при попытке их создать:
Мы легко получили доступ к внутреннему классу HandleBar из класса Main .
Если же мы объявим внутренний класс как private , доступ к созданию объектов у нас будет только внутри «внешнего» класса.
Создать объект Seat снаружи мы уже не сможем:
Наверное, ты уже понял логику 🙂
Модификаторы доступа для внутренних классов работают так же, как и для обычных переменных.
Модификатор protected предоставляет доступ к переменной класса в его классах-наследниках и в классах, которые находятся в том же пакете.
Так же protected работает и для внутренних классов. Объекты protected внутреннего класса можно создавать:
- внутри «внешнего» класса;
- в его классах-наследниках;
- в тех классах, которые находятся в том же пакете.
Если у внутреннего класса нет модификатора доступа ( package private ), объекты внутреннего класса можно создавать
Java. Наследование. Ссылка на объект подкласса. Вызов конструктора суперкласса. Ключевое слово super
Наследование. Ссылка на объект подкласса. Вызов конструктора суперкласса. Ключевое слово super
Содержание
- 1. Можно ли ссылке на суперкласс присвоить ссылку на объект подкласса?
- 2. Можно ли ссылке на подкласс присвоить ссылку на объект суперкласса?
- 3. Какие существуют формы использования ключевого слова super ?
- 4. Как осуществляется вызов из подкласса конструктора суперкласса? Ключевое слово super . Общая форма
- 5. Примеры вызова конструкторов суперкласса из подкласса
- 6. Какие требования относятся к вызову конструктора суперкласса с помощью ключевого слова super ?
- 7. Можно ли вызвать конструктор суперкласса из любого метода подкласса с помощью вызова super ?
- 8. Пример доступа к члену суперкласса из подкласса с использованием ключевого слова super
- 9. Каким образом осуществляется порядок вызова конструкторов в случае наследования? Пример
Поиск на других ресурсах:
1. Можно ли ссылке на суперкласс присвоить ссылку на объект подкласса?
Да, можно. Пусть заданы суперкласс и подкласс. Если объявить ссылку на суперкласс, то этой ссылке можно присвоить значение ссылки на подкласс, который наследует этот суперкласс.
Например. Даны два класса A и B . Класс A есть суперклассом (базовым классом). Класс B есть подклассом класса A .
Тогда, в другом методе можно объявить ссылку на класс A и присвоить этой ссылке значение экземпляра класса B
В случае, когда ссылке на суперкласс rA присваивается ссылка на объект подкласса objB доступными для ссылки rA являются члены класса A , для которого была объявлена эта ссылка. В данном случае ссылке rA доступен член класса A с именем a . Члены класса B есть недоступными для ссылки rA .
Вывод: для ссылки на суперкласс доступные члены класса определяются типом ссылки, а не типом объекта на который эта ссылка ссылается.
Если с помощью ссылки rA попробовать доступиться к члену данных b класса B
то компилятор выдаст ошибку
2. Можно ли ссылке на подкласс присвоить ссылку на объект суперкласса?
Нет, нельзя. Суперкласс не может расширяться до возможностей подкласса. Это противоречит парадигме наследственности. Наоборот, подкласс, который расширяет возможности суперкласса, может «суживаться» к суперклассу.
Например. Пусть заданы два класса A и B . Класс A есть суперклассом (базовым классом). Класс B есть подклассом класса A .
Попытка присвоить ссылке на класс B значение ссылки на класс A
приведет к возникновению критической ситуации с сообщением
3. Какие существуют формы использования ключевого слова super ?
Существуют две формы использования ключевого слова super:
- для вызова конструктора суперкласса;
- для доступа к члену суперкласса из подкласса. Такой доступ нужен в ситуациях, когда имя члена подкласса совпадает с именем члена суперкласса, к которому нужно доступиться из подкласса. В этом случае имя члена данных подкласса перекрывает имя суперкласса.
4. Как осуществляется вызов из подкласса конструктора суперкласса? Ключевое слово super . Общая форма
Конструктор суперкласса (базового класса) может быть вызван из подкласса (производного класса). Этот вызов осуществляется с помощью ключевого слова super. Вызов конструктора суперкласса должен быть осуществлен в теле конструктора подкласса первым.
Общая форма вызова конструктора суперкласса из конструктора подкласса следующая:
- parameters – перечень параметров, которые получает конструктор. Если конструктор не имеет параметров, то конструктор суперкласса вызывается как super() .
5. Примеры вызова конструкторов суперкласса из подкласса
Пример 1. Задан класс Point , описывающий точку на плоскости. Класс расширяется подклассом ColorPoint , который добавляет свойство цвет к точке.
Реализация классов Point и ColorPoint следующая
В вышеприведенном коде, в конструкторах подкласса ColorPoint вызывается конструктор класса Point с помощью ключевого слова super
Пример 2. Вызов конструктора суперкласса в случае многоуровневой наследственности. В примере объявляется 4 класса с именами A1 , A2 , A3 , A4 . Класс A1 есть суперклассом для класса A2 . Класс A2 есть суперклассом для класса A3 . Класс A3 есть суперклассом для класса A4 .
Ниже приведен программный код, демонстрирующий использование ключевого слова super и многоуровневой наследственности
Если создать экземпляр класса A4
то будет выведен следующий результат
В вышеприведенном примере класс A2 наследует все характеристики класса A1 . Класс A3 наследует все характеристики классов A1 , A2 . Класс A4 наследует все характеристики классов A1 , A2 , A3 .
6. Какие требования относятся к вызову конструктора суперкласса с помощью ключевого слова super ?
К вызову конструктора суперкласса с помощью ключевого слова super относятся следующие требования:
- конструктор суперкласса может быть вызван только из конструктора подкласса;
- вызов констуктора суперкласса должно быть первым в конструкторе подкласса;
- вызвать конструктор суперкласса из любого метода подкласса (кроме конструктора) запрещено.
7. Можно ли вызвать конструктор суперкласса из любого метода подкласса с помощью вызова super ?
Нет, нельзя. Если в некотором методе подкласса попробовать вызвать конструктор суперкласса с помощью ключевого слова super() , то компилятор Java выдаст ошибку:
8. Пример доступа к члену суперкласса из подкласса с использованием ключевого слова super
Ключевое слово super используется для доступа к члену суперкласса в случае, если в подклассе используется точно такое же имя.
В вышеприведенном примере член x класса C инициализируется значением x класса B с помощью обращения:
9. Каким образом осуществляется порядок вызова конструкторов в случае наследования? Пример
Если два и более класса образуют иерархию наследования, то конструкторы вызываются в направлении от наивысшего класса в иерархии (от суперкласса) к низшему (к подклассу наиболее низкого уровня).
Например. Заданы 4 класса с именами A , B , C , D . Класс A есть суперклассом для класса B . Класс B есть суперклассом для класса C . Класс C есть суперклассом для класса D .
Java 8 наследование
В предыдущих статьях я уже несколько раз упоминал наследование. Настало время написать подробную статью про эту вещь.
В Java класс может наследоваться от другого класса, получая его методы и поля, который в свою очередь может наследоваться от ещё одного класса и т. д. В Java нет множественного наследования классов. Один класс может наследоваться напрямую только от одного другого класса.
Класс, который наследуется от другого класса, называется подклассом (subclass), дочерним классом (child class), потомком или расширенным классом (extended class).
Класс, от которого наследуется дочерний класс, называется родительским классом (parent class), предком, суперклассом (superclass) или базовым классом (base class).
В самой вершине иерархии наследования находится класс Object , от которого наследуются все классы, для которых не указан явно суперкласс. Таким образом все классы (кроме самого Object ) напрямую или через какое-либо количество уровней наследования наследуются от класса Object .
Идея наследования классов состоит в том, что когда вы хотите создать новый класс, например Goblin , и уже существует какой-нибудь класс, который уже реализует часть функциональности, необходимой нашему классу, например Monster , то вы можете указать этот класс в качестве родительского класса, унаследовав таким образом все его члены (поля, вложенные классы и методы экземпляров). Конструкторы не наследуются и не являются членами классов, но можно вызвать конструктор базового класса из конструктора дочернего класса.
Дочерний класс наследует все public и protected члены своего родителя независимо от пакета, в котором расположен родительский класс. Если дочерний и родительский класс находятся в одном пакете, то дочерний класс наследует также package-private члены своего родителя.
- Унаследованные поля можно использовать напрямую, как все другие поля.
- Можно объявить в дочернем классе поле с таким же именем, как и поле в родительском классе, тогда это поле скроет (hide) поле родительского класса (НЕ рекомендуется так делать).
- В дочернем классе можно объявлять поля, которых нет в родительском классе.
- Унаследованные методы можно использовать напрямую.
- Можно объявить метод экземпляров в дочернем классе с точно такой же сигнатурой, что и метод экземпляров в родительском классе, тогда этот метод переопределит (override) метод суперкласса.
- Можно объявить в дочернем классе статический метод с точно такой же сигнатурой, что и статический метод в родительском классе, тогда этот метод скроет (hide) метод родительского класса.
- В дочернем классе можно объявлять новые методы, которых нет в родительском классе.
- В дочернем классе можно объявить конструктор, который будет явно (с помощью ключевого слова super ) или неявно вызывать конструктор базового класса.
Дочерний класс не наследует private члены родительского класса, однако если в родительском классе есть protected , public или package-private (для случая нахождения дочернего и родительского класса в одном пакете) методы для доступа к private полям, то они могут использоваться дочерним классом.