Содержание
- Что такое наследование?
- Каковы преимущества наследования?
- Особенности наследования
- Замечания по использованию наследования
- В чём разница между super и this?
- Переопределение методов (перезапись)
- Ключевое слово final
- Полиморфизм
- Абстракция (abstract)
- Внутренние классы
- Содержимое, изменяемое различными модификаторами (не связано с внутренними классами)
- Четыре модификатора доступа
Что такое наследование?
Когда несколько классов имеют одинаковые атрибуты и поведение, вынесите это содержимое в один класс. Тогда этим нескольким классам больше не нужно определять эти атрибуты и поведение; им нужно лишь унаследовать этот класс.
Эти несколько классов можно назватьподклассами, а этот единственный класс называетсяродительским классом、, суперклассомилибазовый класс。
Подклассы могут напрямую обращаться кнеприватныматрибутам и поведению в родительском классе.
С помощью ключевого словаextendsмежду классами создаётся отношение наследования.
class SubDemo extends Demo{} //SubDemo是子类,Demo是父类
Каковы преимущества наследования?
- Повышаетвозможность повторного использования кода。
- Создаёт отношения между классами, что являетсяпредпосылкой для полиморфизма.。
Особенности наследования
1. Java поддерживает только одиночное наследование, а не множественное наследование.
//一个类只能有一个父类,不可以有多个父类。
class SubDemo extends Demo{} //ok
class SubDemo extends Demo1,Demo2...//error
2. Java поддерживает многоуровневое (повторное) наследование (иерархию наследования).
class A{}
class B extends A{}
class C extends B{}
Замечания по использованию наследования
- Если между классами существует отношение "is a", рассмотрите возможность использования наследования.
- Не используйте наследование только для того, чтобы унаследовать часть функциональности.
В чём разница между super и this?
supersuper — это ключевое слово, которое представляетидентификатор области памяти родительского класса. (Его можно понимать как ссылку на родителя.)
Использование super и this аналогично.
this представляетссылку на объект(кто бы его ни вызывал, он представляет этот объект);
super представляетссылку на родительский классPairтекущего подкласса.
Сценарии использования
- Когда у дочернего и родительского классов есть члены с одинаковыми именами, для их различения можно использовать super;
- Когда подклассу нужно вызвать конструктор родительского класса, можно использовать оператор super.
Различия
1. Переменные-члены
this.变量 -- 本类的 super.变量 -- 父类的
2. Конструкторы
this(...) -- 本类的 super(...) -- 父类的
3. Методы-члены
this.方法名() -- 本类的 super.方法名() -- 父类的
super(); и this(); должны оба находиться в первой строке конструктора, и они не могут появляться одновременно.
Переопределение методов (перезапись)
Когда в подклассе есть метод, полностью совпадающий с методом родительского класса (за исключением модификатора доступа; модификатор доступа должен быть больше или равен и не private; тип возвращаемого значения, имя метода и список параметров совпадают), происходит операция переопределения, также называемая переписыванием или перезаписью.
private-методы родительского класса невидимы для подкласса, поэтому переопределение private-методов родительского класса исключено.
Примечания по переопределению:
- При переопределении уровень доступа метода подкласса должен быть больше или равен уровню доступа метода родительского класса;
- static-методы могут переопределять только static-методы.
Случаи использования переопределения:
Когда подклассу нужна функциональность родительского класса, но тело метода содержит содержимое, специфичное для подкласса, метод в родительском классе можно переопределить. Таким образом, он не только наследует функциональность родительского класса, но и определяет содержимое, специфичное для подкласса.
В чём разница между переопределением методов и перегрузкой методов??
Переопределение метода используется, когда метод подкласса полностью совпадает с методом родительского класса; кроме модификатора доступа, возвращаемый тип, имя метода и список параметров совпадают.
Перегрузка используется, когда методы в одном и том же классе имеют одинаковое имя метода, но разные списки параметров (это не имеет отношения к возвращаемому типу).
Использование конструкторов в дочернем и родительском классах:
- Во время инициализации подкласса сначала выполняется инициализация родительского класса. Это связано с тем, что конструктор подкласса содержит вызов super() по умолчанию. Подклассу нужно использовать переменные-члены родительского класса, и эта инициализация должна быть завершена до инициализации подкласса. Поэтому при инициализации подкласса сначала выполняется инициализация родительского класса.
- Если в родительском классе нет конструктора без аргументов
- Используйте super для вызова параметризованного конструктора родительского класса. Рекомендуемый подход.
- Используйте this для вызова других конструкторов того же класса.
Порядок выполнения статических блоков кода, блоков кода конструктора и конструкторов:
Статический блок кода родительского класса → статический блок кода подкласса → блок кода конструктора родительского класса → конструктор родительского класса → блок кода конструктора подкласса → конструктор подкласса
Ключевое слово final
final — это ключевое слово, которое можно использовать для модификации классов, переменных-членов и методов-членов.
Характеристики:
- Класс, который он модифицирует, не может быть унаследован.
- Переменная-член, которую он модифицирует, является константой.
- Метод-член, который он модифицирует, не может быть переопределён подклассами.
Константы, модифицированные final, обычно имеют соглашения об именовании. Для констант, модифицированных final, все буквызаглавные.。
Переменная-член, модифицированная final, должна быть инициализирована. Есть два способа её инициализировать:
- Явная инициализация;
- Инициализация в конструкторе.
Но эти два способа нельзя использовать вместе для инициализации.
Разница между final и private:
- Класс, модифицированный final, доступен;
private не может модифицировать внешние классы, но может модифицировать внутренние классы (на самом деле делать внешний класс private бессмысленно). - Методы, модифицированные final, не могут быть переопределены подклассами;
Методы, модифицированные private, выглядят так, будто их можно переопределить в подклассах, но на самом деле это невозможно, потому что подклассы не видят private-методы родительского класса. - Переменная, модифицированная final, может быть присвоена только один раз при явной инициализации или инициализации в конструкторе, и после этого её нельзя изменить;
Переменная, модифицированная private, также не позволяет подклассам или другим классам в том же пакете напрямую обращаться к ней или изменять её, но её можно изменять и получать через методы set и get.
Полиморфизм
Концепция:
Различные состояния, которые объект проявляет в разные моменты времени.
Предварительные условия полиморфизма:
- Должно существовать отношение наследования или реализации.
- Должно быть переопределение методов.
- Должна быть ссылка родительского класса, указывающая на объект подкласса.
Проявление в программах:
Ссылка родительского класса или интерфейса указывает на собственныйобъект подкласса или принимает его.。
Преимущества и эффекты:
Существование полиморфизма улучшает программнуюрасширяемостьи последующуюсопровождаемость.。
Недостатки:
Когда вызывается родительский класс, можно вызывать только методы родительского класса, а не специфические методы подкласса, потому что вы не знаете, какие подклассы унаследуют его в будущем.
Особенности членов при полиморфизме:
- Переменные-члены: Во время компиляции: проверяется, есть ли в классе, к которому относится ссылочная переменная, вызываемая переменная;
Во время выполнения: также проверяется, есть ли в классе, к которому относится ссылочная переменная, вызываемая переменная.
Для переменных-членов и время компиляции, и время выполнения зависят от класса, к которому относится ссылочная переменная. Просто запомните:Для переменных-членов и компиляция, и выполнение смотрят на левую часть знака равенства.。 - Методы-члены: Во время компиляции: проверяется, есть ли в классе, к которому относится ссылочная переменная, вызываемый член;
Во время выполнения: проверяется, есть ли в классе, к которому относится объект, вызываемый член. Если у родителя и потомка есть методы с одинаковым именем, будет выполняться метод подкласса, потому что методы обладают характеристикой переопределения.
Компиляция смотрит налево, время выполнения — направо.。 - Статические методы: Во время компиляции: проверяется, есть ли в классе, к которому относится ссылочная переменная, вызываемая переменная;
Во время выполнения: также проверяется, есть ли в классе, к которому относится ссылочная переменная, вызываемая переменная.
И компиляция, и время выполнения смотрят на левую часть знака равенства.。
Ни в коем случае нельзя преобразовывать объект родительского класса к типу подкласса!
Ссылка на родительский класс, указывающая на объект подкласса, может быть повышена, а также может бытьпринудительно приведена/преобразована.。
При полиморфизме всегда изменяется именно объект подкласса!
//多态向下转型和向上转型的例子,多态转型解决了多态中父类引用不能使用子类特有成员的弊端。
class PolymorphicTest2 {
public static void main(String[] args) {
Phone p1 = new Nokia(); //向上转型,类型提升
Nokia no = (Nokia)p1; //向下转型,强制将父类的引用转换成子类类型,不能将Nokia类型转成Moto或Nexus类型
no.print(); //输出结果为Phone---null---0,因为继承了父类的方法
Phone p2 = new Moto();
Moto m = (Moto)p2;
m.print(); //输出结果为Moto---yellow---1599,方法重写,子类方法覆盖父类方法
Phone p3 = new Nexus();
Nexus ne = (Nexus)p3;
ne.print();
}
}
class Phone{
String color;
int price;
public void print(){
System.out.println("Phone---" + color + "---" + price );
}
}
class Nokia extends Phone{
String color = "red";
int price = 1009;
//public void print(){
// System.out.println("Nokia---" + color + "---" + price);
//}
}
class Moto extends Phone{
String color = "yellow";
int price = 1599;
public void print(){
System.out.println("Moto---" + color + "---" + price);
}
}
class Nexus extends Phone{
String color = "black";
int price = 1999;
public void print(){
System.out.println("Nexus---" + color + "---" + price);
}
}
}
Абстракция (abstract)
Абстракция — это извлечение общего и существенного содержания из множества вещей.
Абстрактные классы:
В Java можно определитьметоды без тела метода.Конкретную реализацию такого метода предоставляетподкласс.Неполный метод называется абстрактным методом, а класс, содержащий абстрактный метод, является абстрактным классом.
Происхождение:
Когда несколько объектов имеют одну и ту же функцию, но конкретное содержимое функции различается, в процессе извлечения извлекается только определение функции, а не тело функции. Метод, имеющий только объявление функции и не имеющий тела функции, называется абстрактным методом.
Особенности абстрактных классов:
- Абстрактные методы должны находиться в абстрактном классе;
- И абстрактные методы, и абстрактные классы должны быть помечены ключевым словом `abstract`;
- Абстрактные классы не могут использовать `new` для создания объектов, потому что вызов абстрактного метода не имеет смысла;
- Чтобы абстрактные методы в абстрактном классе можно было использовать, подкласс должен переопределить все его абстрактные методы, а затем создать объект подкласса, чтобы вызывать их; если подкласс переопределяет только часть абстрактных методов, он всё ещё остаётся абстрактным классом;
- Абстрактный класс может иметь абстрактные методы или неабстрактные методы; абстрактные методы используются для создания экземпляра подкласса;
- Если класс является абстрактным, то наследующие его подклассы должны либо быть абстрактными классами, либо переопределить все абстрактные методы.
Особый случай: абстрактный класс может не определять абстрактные методы; это делается только для того, чтобы запретить создание объектов этого класса.
Характеристики членов абстрактных классов:
- Переменные-члены: могут быть переменными или константами;
- Конструкторы: конструкторы есть;
- Методы-члены: могут быть абстрактными или неабстрактными методами.
abstract class 葵花宝典 {
public abstract void 自宫();
}
class 岳不群 extends 葵花宝典 {
public void 自宫(){
System.out.println("剪刀");
}
}
class 林平之 extends 葵花宝典{
public void 自宫(){
System.out.println("指甲刀");
}
}
class AbstractTest {
public static void main(String[] args) {
岳不群 岳 = new 岳不群();
岳.自宫();
林平之 林 = new 林平之();
林.自宫();
}
}
Меры предосторожности при работе с абстрактными классами:
Абстрактный класс нельзя инстанцировать; почему у него всё ещё есть конструктор??
Если класс определён с помощью `class`, у него обязательно должен быть конструктор. Конструктор в абстрактном классе используется для инстанцирования подклассов.
У класса нет абстрактных методов; почему он определён как абстрактный класс??
Он хочет, чтобы его наследовали, но не создавали его экземпляры.
Какие ключевые слова не могут использоваться вместе с ключевым словом `abstract`??
- `final`: если метод абстрактный, его нужно переопределить, но `final` нельзя переопределить, поэтому они конфликтуют.
- `private`: если метод приватный, подклассы не могут напрямую обращаться к нему, так как же его можно переопределить?
- `static`: объект не нужен, и абстрактный метод можно вызвать по имени класса. Но вызов абстрактного метода не имеет смысла.
Интерфейс (`interface`)
Интерфейс— этоабстрактные методыиконстантыкак совокупность. По сути, интерфейс — это особый вид абстрактного класса, содержащий только константы и определения методов, без переменных и реализаций методов.
Формат:`interface InterfaceName {}`
Появление интерфейсов выражает «множественное наследование» в другой форме, а именно «множественную реализацию».
Реализация (`implements`)
Формат:`class ClassName implements InterfaceName {}`
Характеристики:
- Интерфейсы нельзя инстанцировать.
- Если класс реализует интерфейс, он должен быть либо абстрактным классом, либо реализовывать все методы интерфейса.
Характеристики членов интерфейсов:
Модификаторы членов интерфейса фиксированы!
- Константы-члены: `public static final`. Переменные, определённые в интерфейсе, являются глобальными константами, и модификаторами могут быть только эти три ключевых слова; все их можно опустить. Имена констант должны быть написаны заглавными буквами.
- Методы-члены: `public abstract`. Методы, определённые в интерфейсе, все являются абстрактными, и эти два ключевых слова-модификатора можно опустить.
- Рекомендация: всегда указывайте модификаторы вручную.
Различия между наследованием и реализацией:
- Связь между классами и классами называется наследованием: потому что независимо от того, является ли класс абстрактным или неабстрактным, он может определять внутри неабстрактные методы, и эти методы могут напрямую использоваться подклассами; подклассам достаточно лишь унаследовать. Допускается только одиночное наследование, а также допускается многоуровневое наследование.(class))
- Связь между классом и интерфейсом — это реализация: потому что все методы в интерфейсе абстрактны, они должны быть реализованы подклассом, прежде чем его можно будет инстанцировать. Класс может иметь одну реализацию или несколько реализаций; он также может реализовывать несколько интерфейсов, одновременно наследуя класс.(class) extends (class) implements (interface1,interface2…))
- Связь между интерфейсами и интерфейсами — это наследование: один интерфейс может наследовать другой интерфейс и добавлять новые свойства и абстрактные методы, а интерфейсы могут иметь множественное наследование.(interface) extends (interface1,interface2…))
Различия между абстрактными классами и интерфейсами:
Переменные-члены
- Абстрактный класс может иметь переменные и константы
- Интерфейс может содержать только константы
Методы-члены
- Абстрактный класс может иметь неабстрактные методы и абстрактные методы
- Интерфейс может содержать только абстрактные методы
Конструкторы
- Абстрактные классы имеют конструкторы
- Интерфейсы не имеют конструкторов
Связь между классами, абстрактными классами и интерфейсами
- Связь между классом и абстрактным классом — это наследование `extends`
- Связь между классом и интерфейсом — это реализация `implements`
Концептуальные характеристики интерфейсов:
- Интерфейс — этовнешне предоставляемыеправила;
- Интерфейс — этофункциональное расширение;
- программы;Появление интерфейсовснижает связанность; (это реализует модульную разработку: правила определены, каждый реализует свой модуль, что значительно повышает эффективность разработки)
- Интерфейсы могут использоваться длямножественной реализации;
- Нескольконесвязанных классов могут реализовывать один и тот же интерфейс;
- Класс может реализовыватьнесколькоинтерфейсов, не имеющих прямой связи друг с другом;
- Подобно отношению наследования, между интерфейсом и его классом реализации существуетполиморфизм。
//运动员和教练的案例(下图是思路分析)
/*
篮球运动员和教练
乒乓球运动员和教练
现在篮球运动员和教练要出国访问,需要学习英语
请根据你所学的知识,分析出来哪些是类,哪些是抽象类,哪些是接口
*/
interface SpeakEnglish {
public abstract void speak();
}
interface GoAboard{
public abstract void aboard();
}
abstract class Person {
private String name;
private int age;
public Person(){}
public Person(String name,int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
//吃饭
public abstract void eat();
//睡觉
public void sleep(){
System.out.println("Zzz...");
}
}
//运动员
abstract class Player extends Person {
public abstract void study();
}
//教练
abstract class Coach extends Person {
public abstract void teach();
}
//篮球运动员
class BasketballPlayer extends Player implements SpeakEnglish,GoAboard{
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "吃鸡腿");
}
public void study(){
System.out.println(getAge() + "岁的" + getName() + "学扣篮");
}
public void speak(){
System.out.println(getAge() + "岁的" + getName() + " Say Hello World");
}
public void aboard(){
System.out.println(getAge() + "岁的" + getName() + " Go Aboard");
}
}
//乒乓运动员
class PingPangPlayer extends Player{
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "吃鸡蛋");
}
public void study(){
System.out.println(getAge() + "岁的" + getName() + "学扣球");
}
}
//篮球教练
class BasketballCoach extends Coach implements SpeakEnglish {
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "啃鸡爪");
}
public void teach(){
System.out.println(getAge() + "岁的" + getName() + "教扣篮");
}
public void speak(){
System.out.println(getAge() + "岁的" + getName() + " Say Hello Java");
}
public void aboard(){
System.out.println(getAge() + "岁的" + getName() + " Go Aboard");
}
}
//乒乓球教练
class PingPangCoach extends Coach{
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "吃鸡蛋皮");
}
public void teach(){
System.out.println(getAge() + "岁的" + getName() + "教扣球");
}
}
class PlayerAndCoach {
public static void main(String[] args) {
//篮球运动员
BasketballPlayer bp = new BasketballPlayer();
bp.setName("郭艾伦");
bp.setAge(33);
bp.eat();
bp.sleep();
bp.study();
bp.speak();
bp.aboard();
System.out.println("***********************");
//篮球教练
BasketballCoach bc = new BasketballCoach();
bc.setName("波波维奇");
bc.setAge(65);
bc.eat();
bc.sleep();
bc.teach();
bc.speak();
bc.aboard();
System.out.println("***********************");
//多态
Person p = new BasketballPlayer();
p.setName("Kobe Bryant");
p.setAge(33);
p.eat();
p.sleep();
//p.study();
//p.speak();
BasketballPlayer bp2 = (BasketballPlayer)p;
bp2.study();
bp2.speak();
bp2.aboard();
System.out.println("***********************");
}
}
Внутренние классы
Определение класса внутри другого класса; внутренний класс называется внутренним классом. Появление внутренних классов в очередной раз преодолевает ограничение одиночного наследования Java.
Особенности доступа:
- Внутренний класс может напрямую обращаться к членам внешнего класса, включая приватные члены.
- Чтобы внешний класс мог получить доступ к членам внутреннего класса, он должен создать объект внутреннего класса.
Классификация и общность внутренних классов:
Общность:
- Внутренний класс по-прежнему является независимым классом. После компиляции внутренний класс компилируется в независимый файл `.class`, но к его имени добавляется префикс из имени внешнего класса и символа `$`.
- К внутренним классам нельзя получить доступ обычным способом. Внутренний класс является членом внешнего класса, поэтому он может свободно обращаться к переменным-членам внешнего класса, независимо от того, являются ли они приватными.
Внутренний класс-член
Во внешнем классе есть переменные-члены и методы-члены; внутренний класс-член рассматривает целый класс как член внешнего класса.
Внутренний класс-член определяетсявнутри класса, но вне методовкласса.
Формат создания объекта:`OuterClassName.InnerClassName objectName = outerClassObject.innerClassObject`;
Причина, по которой внутренний класс-член может напрямую обращаться к членам внешнего класса, заключается в том, что внутренний класс хранит ссылку на объект внешнего класса:`OuterClassName.this`;
Для внутренних классов-членов можно использовать модификаторы `final`, `abstract`, `public`, `private`, `protected`, `static`.
Статический внутренний класс
Статический внутренний класс — это внутренний класс-член с модификатором static `static`, определённыйвнутри класса, но вне методов.。
Существует два сценария доступа к статическому внутреннему классу из внешнего класса:
- Доступ к нестатическим членам статического внутреннего класса из внешнего класса:`*OuterClassName.InnerClassName objectName = OuterClassName.innerObject*`Для доступа к ним нужно создать объект;
- Доступ к статическим членам статического внутреннего класса из внешнего класса: можно также использовать приведённый выше формат или напрямую использовать`OuterClassName.InnerClassName.member`。
Локальный внутренний класс
Локальный внутренний класс — это класс, определённый внутри метода.
- Внутренний класс, объявленный в методе, можно создать тольковнутри метода, в котором он определён,и нельзя создать вне этого метода.
- Объект внутреннего класса, объявленного в методе, не может использовать не-final локальные переменные метода, в котором находится внутренний класс.
Модификаторы, которые можно использовать для внутреннего класса, объявленного в методе:final, abstract;
Внутренний класс, объявленный в статическом методе, может получать доступ толькок статическим членам внешнего класса.。
Анонимный внутренний класс
Анонимный внутренний класс — это упрощённая форма внутреннего класса; он создаёт объект анонимного подкласса, содержимое которого наследует внешний класс или реализует интерфейс.
Предварительное условие:
Внутренний класс может наследовать внешний класс или реализовывать интерфейс.
Формат:
`new OuterClassNameOrInterfaceName() { override methods };`
Обычно, когда формальный параметр метода — интерфейс или абстрактный класс, и интерфейс имеет не более трёх методов, анонимный внутренний класс можно передать в качестве аргумента.
Содержимое, изменяемое различными модификаторами (не связано с внутренними классами)
| Класс | Переменные-члены | Методы-члены | Конструкторы | |
|---|---|---|---|---|
| private | Y | Y | Y | |
| Default | Y | Y | Y | Y |
| protected | Y | Y | Y | |
| public | Y | Y | Y | Y |
| abstract | Y | Y | ||
| static | Y | Y | Y | |
| final | Y | Y | Y |
Примечание: общие правила таковы:
- В дальнейшем все классы следует объявлять с модификатором `public`. Кроме того, в одном Java-файле следует писать только один класс.
- В дальнейшем все переменные-члены следует объявлять с модификатором `private`.
- В дальнейшем все методы-члены следует объявлять с модификатором `public`.
Если это абстрактный класс или интерфейс: `public abstract` + ... - С этого момента все конструкторы должны быть объявлены с модификатором public.
Если класс является служебным классом или синглтоном: используйте private для модификации конструктора.
Четыре модификатора доступа
| Тот же класс | Тот же пакет (несвязанные классы или подклассы) | Другой пакет (подклассы) | Другой пакет (несвязанные классы) | |
|---|---|---|---|---|
| private | Y | |||
| Default | Y | Y | ||
| protected | Y | Y | Y | |
| public | Y | Y | Y | Y |
Рекомендация:
- Переменные-члены: private
- Конструктор: public
- Методы-члены: public
Больше руководств
Для более подробных руководств обратитесь к:Учебник по Java
Источник: http://www.codeceo.com/article/java-extends.html