Как сделать класс наследник java

Добавил пользователь Алексей Ф.
Обновлено: 05.10.2024

как создать сайт на wordpress, настроить и оптимизировать wordpress

Затем этот класс может наследоваться другими, более специализированными, классами, каждый из которых будет добавлять свои уникальные характеристики.
В терминологии Java наследуемый класс называют суперклассом. Наследующий класс носит название подкласса. Следовательно, подкласс — это специализированная версия суперкласса. Он наследует все члены, определенные суперклассом, и добавляет собственные, уникальные, элементы.

Чтобы наследовать класс, достаточно просто вставить определение одного
класса в другой с использованием ключевого слова extends.

В качестве иллюстрации рассмотрим короткий пример. Следующая программа создает суперкласс А и подкласс В. Обратите внимание на использование ключевого слова extends для создания подкласса класса А.

Эта программа создает следующий вывод:

Содержимое superOb:
i и j: 10 20
Содержимое subOb:
i и j : 7 8
k: 9
Сумма i, j и k в subOb:
i+j+k: 24

Как видите, подкласс В включает в себя все члены своего суперкласса А. Именно поэтому объект subOb имеет доступ к переменным i и j и может вызывать метод showij().
Кроме того, внутри метода sum() возможна непосредственная ссылка
на переменные i и j, как если бы они были частью класса В.

Несмотря на то, что А — суперкласс класса В, он также является полностью независимым, самостоятельным классом. То, что класс является суперклассом подкласса, не означает невозможность его самостоятельного использования. Более того, подкласс может быть суперклассом другого подкласса.

Общая форма объявления класса, который наследуется от суперкласса, следующая.

Для каждого создаваемого подкласса можно указывать только один суперкласс.
Язык Java не поддерживает наследование нескольких суперклассов в одном
подклассе. Как было сказано, можно создать иерархию наследования, в которой подкласс становится суперклассом другого подкласса. Однако никакой класс не может быть собственным суперклассом.

Хотя подкласс включает в себя все члены своего суперкласса, он не может получать доступ к тем членам суперкласса, которые объявлены как private.
Например, рассмотрим следующую простую иерархию классов.

Компиляция этой программы будет невозможна, поскольку использование переменной j внутри метода sum() класса В приводит к нарушению правил доступа.
Поскольку переменная j объявлена как private, она доступна только другим членам ее собственного класса. Подкласс не имеет к ней доступа.

Рассмотрим еще один пример, который поможет проиллюстрировать
возможности наследования.

Эта программа создает следующий вывод:
Объем myboxl равен 3000.0
Вес myboxl равен 34.3
Объем mybox2 равен 24.0
Bee mybox2 равен 0.076

Класс BoxWeight наследует все характеристики класса Box и добавляет к ним компонент weight.
Классу BoxWeight не нужно воссоздавать все характеристики класса Box. Он может просто расширять класс Box в соответствии с конкретными
целями.

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

Например, следующий класс наследует характеристики класса Box и добавляет атрибут цвета.

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

И вдруг заказчик решает добавить цветную коробку - ColorBox и тяжелую коробку - HeavyBox . Цветная коробка будет отличаться от обычной только цветом, а тяжелая - весом. Получается, что в класс ColorBox мы должны добавить те же переменные width , height и depth , конструкторы и методы, которые существуют в классе Box . Дублирование кода в программировании не приветствуется, поэтому для таких случаев придуман такой механизм как наследование.

Используя наследование Java, можно создать класс, который определяет характеристики, общие для набора связанных элементов - Box . Затем этот общий класс может наследоваться другими, более специализированными классами ColorBox и HeavyBox , каждый из которых будет добавлять свои особые характеристики.

В терминологии Java наследуемый класс называется супер классом, а наследующий класс – подклассом. Подкласс наследует все члены, определенные в супер классе, добавляя к ним собственные, особые элементы. Набор классов, связанных отношением наследования, называют иерархией, что изображается таким образом:

Пример наследования фото

Общая форма объявления класса, который наследуется от супер класса:

Для каждого создаваемого подкласса можно указать только один супер класс. Класс не может стать супер классом для самого себя.

В объявлении класса ColorBox используется ключевое слово extends для указания того, что ColorBox является наследником Box6 . ColorBox содержит все переменные и методы класса Box6 несмотря на то, что в самом классе ColorBox они не указаны.

Один класс может содержать несколько наследников - класс HeavyBox тоже расширяет Box6 :

В следующем классе создаем объекты всех трех типов и подсчитываем объем для каждой коробки.

2. Доступ к членам класса и наследование

Несмотря на то, что подкласс включает в себя все члены своего супер класса, он не может иметь доступ к тем членам супер класса, которые объявлены как private :

Из класса B , который является наследником класса A , невозможно напрямую обратиться к private переменной класса A . Доступ к ним можно получить через геттер методы:

3. Переменная супер класса может ссылаться на объект подкласса

Ссылочной переменной супер класса может быть присвоена ссылка на любой его подкласс.

Например, переменная heavyBox объявлена как Box , но она указывает на объект типа HeavyBox :

Обратное неверно! Нельзя написать так: HeavyBox heavyBox = new Box(15, 10, 20).

В следующем примере объявлено три переменные типа Box6 , но они указывают на разные объекты.

Для каждого объекта мы можем узнать его ширину, но при попытке обратиться к переменной color объекта redBox , возникнет ошибка компиляции. В чем причина такого поведения? Переменная color объявлена в классе ColorBox с уровнем доступа по умолчанию, класс DifferentBoxDemo2 находится в том же пакете, то есть переменная color должна быть доступна. Дело в том, что доступные члены класса определяются типом ссылочной переменной, а не типом объекта, на который она ссылается. То есть если переменная объявлена типа Box6 , нам доступны только члены объявленные в классе Box6 ( weight , height , depth ), и неважно на какой объект она ссылается. А вот для переменной blueBox мы можем узнать цвет, так как переменная объявлена как ColorBox :

4. Создание многоуровневой иерархии

Можно строить иерархии, состоящие из любого количества уровней наследования. Например, добавим класс Shipment , расширяющий HeavyBox :

Создание многоуровневой иерархии фото

Класс Shipment содержит не только переменную cost , объявленную в самом классе, но и переменные класса HeavyBox и Box6 :

5. Порядок вызова конструкторов в многоуровневой иерархии

В иерархии классов конструкторы выполняются в порядке наследования, начиная с супер класса и кончая подклассом. Рассмотрим следующую иерархию классов:

При создании объекта класса G , сначала закончит свое выполнение конструктор класса E , потом F и в конце G :

alt text

Внимание оговорки:

  • 16:51 Доступен метод предка, а не потомка.
  • 22:30 вместо слова "метод" подразумевается слово "класс".

В этом уроке Вы добавляете наследование в java в копилку своих знаний.

Код, примеры из которого приведены здесь, можно взять вот в этом репозитории.

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

  • Все классы в мире java, косвенно или прямо, являются наследниками класса Object .
  • Наследоваться можно только от одного класса.

Для того что бы некий класс стал наследником другого класса, в его объявлении применяется ключевое слово extends и имя наследуемого класса. Вот как это выглядит в коде:

Но мы не можем написать так: class Primate extends Animal, SomeClass, Foo < . Наследоваться можно только от одного класса.

Член класса — это либо метод, либо поле класса.

Для чего нужно это наследование?

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

Для разнообразия приведу пример не на ветвлении класса Game , а на упрощенной классификации животных.

Начнем с класса Animal :

Не зависимо от типа, животное может быть живым или мертвым и иметь некий возраст. Пока этих полей хватит.

Далее создадим класс приматов:

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

Далее создадим класс обезьян:

Будем классифицировать обезьян по диете и на этом успокоимся. Но каждая обезьяна точно должна включать в себя все параметры примата. Поэтому класс Monkey наследуется от класса Primate . Получается, что в классе Monkey мы уже не дублируем шесть полей и кучу методов к ним, а переиспользуем уже написанное!

В упомянутом выше репозитории Вы еще найдете класс HomoSapiens как пример ветвления наследников.

Как использовать наследование?

Сразу же начнем с примера использования объекта класса Monkey . Вертеть ее будем в классе CrittersUsage .

Как видно из кода — объекту класса Monkey доступны все члены всех классов-предков. Даже Object.toString() . Реализован Object.toString() слишком обобщенно, поэтому данный метод просто возвращает системное имя объекта, у которого он был вызван. В моем случае это было com.critters.Monkey@1b6d3586 .

Доступность членов классов-предков в классах-наследниках

Обратите внимание на то, что ссылки в аргументах методов printAnimalAge & printAnimalAliveStatus имеют тип Animal . Это хоть и позволяет этим методам принимать на вход объекты-наследники от класса Animal , но это же ограничивает доступность членов объекта для данных методов. Тип ссылки ограничивает видимость членов объекта по себе. То есть, несмотря на то, что мы знаем, что в ссылках someAnimal на самом деле представлен объект класса Monkey , но мы сможем использовать только члены класса (типа) Animal : isAlive(), setAlive(. ), getAge(), setAge(. ) , в выше упомянутых методах. А поля класса Animal видны только в рамках пакета critters , потому что они не имеют модификатора доступа.

Это означает, что видимость членов классов в наследовании работает только на верх. Наследники наследуют все свойства предков, а предкам недоступны свойства наследников.

super — ключевое слово, позволяющее наследнику получить доступ к членам класса-предка, которые перекрыты такими же членами класса-наследника. Но наследник:

  • не имеет доступа к private членам класса-предка;
  • может иметь доступ к членам, которые без модификатора доступа, если лежит с предком в одном пакете;
  • может иметь доступ к членам класса-предка, которые с модификатором protected , не зависимо от расположения в пакетах.

Естественно, что public члены любого класса светятся во весь мир.

Рассмотрим на примерах.

Для начала, добавим:

  • в класс Animal строку protected final String hiddenMember = "Animal's hidden string."; .
  • в класс Primate строки protected final String hiddenMember = "Primate's hidden first string."; и private final String secondHiddenMember = "Primate's hidden second string."; .
  • в класс Monkey строку protected final String hiddenMember = "Monkeys's hidden string."; . И Добавим еще сюда метод accessToHiddenMembers() .

Теперь класс Monkey будет выглядеть так:

Обратите внимание, что при помощи слова super мы получили доступ к полю hiddenMember класса Primate . Хотя мы его перекрыли таким же полем в классе Monkey .

Но мы не можем получить доступ к скрытому члену класса-предка-предка Animal . Хотя можем пройтись по всем другим членам классов-предков вплоть до Object . Перекрывая член класса-предка — теряем доступ к этому члену во всех классах-предках, кроме ближайшего.

В случае наследования в Java для указания родительского класса используется ключевое слово extends, которое следует после имени дочернего, т. е. производного, класса. После extends пишется родительский класс. Другими словами, "дочерний класс расширяет родительский".

В Java нет множественного наследования от классов, но есть множественное наследование интерфейсов.

В Java есть особенность, связанная с наследованием конструкторов и их вызовом. В конструкторе дочернего класса, перед тем как будут выполнены выражения тела, неявно вызывается дефолтный (без параметров) конструктор предка.

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

В приведенном выше примере ошибка возникает на уровне конструктора класса Child. Перед тем как выполнится выражение this.b = b, будет неявно вызван конструктор Parent без параметров. Однако такого конструктора в родительском классе нет.

Если мы закомментируем или удалим конструктор Parent,

то ошибка в дочернем классе исчезнет. Дело в том, что в Java любой класс есть потомок базового класса Object, у которого всегда имеется пустой дефолтный конструктор. В данном случае, двигаясь по дереву наследования к корню, из Child будет вызываться конструктор базового для всех класса.

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

Заметим, что у объектов Child поле this.a существует, даже если ему не было присвоено значение. В данном случае значение будет нулевым.

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

Другой распространенный вариант – когда в дочернем классе явно вызывается конструктор родительского класса с помощью ключевого слова super. Причем вызывать всегда надо первой строчкой тела конструктора.

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

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

Также возможно сужение типа, когда объект, связанный с переменной родительского типа, присваивается переменной дочернего, то есть своего типа. В этих случаях, чтобы избежать ошибок, следует проверять тип объекта. Например, пусть класс B производный от класса A. Тогда:

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

Читайте также: