Содержание

  1. Что такое наследование?
  2. Каковы преимущества наследования?
  3. Особенности наследования
  4. Замечания по использованию наследования
  5. В чём разница между super и this?
  6. Переопределение методов (перезапись)
  7. Ключевое слово final
  8. Полиморфизм
  9. Абстракция (abstract)
  10. Внутренние классы
  11. Содержимое, изменяемое различными модификаторами (не связано с внутренними классами)
  12. Четыре модификатора доступа

Что такое наследование?

Когда несколько классов имеют одинаковые атрибуты и поведение, вынесите это содержимое в один класс. Тогда этим нескольким классам больше не нужно определять эти атрибуты и поведение; им нужно лишь унаследовать этот класс.

Эти несколько классов можно назватьподклассами, а этот единственный класс называетсяродительским классом、, суперклассомилибазовый класс。

Подклассы могут напрямую обращаться кнеприватныматрибутам и поведению в родительском классе.

С помощью ключевого слова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-методы.

Случаи использования переопределения:

Когда подклассу нужна функциональность родительского класса, но тело метода содержит содержимое, специфичное для подкласса, метод в родительском классе можно переопределить. Таким образом, он не только наследует функциональность родительского класса, но и определяет содержимое, специфичное для подкласса.

В чём разница между переопределением методов и перегрузкой методов??

Переопределение метода используется, когда метод подкласса полностью совпадает с методом родительского класса; кроме модификатора доступа, возвращаемый тип, имя метода и список параметров совпадают.
Перегрузка используется, когда методы в одном и том же классе имеют одинаковое имя метода, но разные списки параметров (это не имеет отношения к возвращаемому типу).

Использование конструкторов в дочернем и родительском классах:

  1. Во время инициализации подкласса сначала выполняется инициализация родительского класса. Это связано с тем, что конструктор подкласса содержит вызов super() по умолчанию. Подклассу нужно использовать переменные-члены родительского класса, и эта инициализация должна быть завершена до инициализации подкласса. Поэтому при инициализации подкласса сначала выполняется инициализация родительского класса.
  2. Если в родительском классе нет конструктора без аргументов
  • Используйте super для вызова параметризованного конструктора родительского класса. Рекомендуемый подход.
  • Используйте this для вызова других конструкторов того же класса.

Порядок выполнения статических блоков кода, блоков кода конструктора и конструкторов:

Статический блок кода родительского класса → статический блок кода подкласса → блок кода конструктора родительского класса → конструктор родительского класса → блок кода конструктора подкласса → конструктор подкласса

Ключевое слово final

final — это ключевое слово, которое можно использовать для модификации классов, переменных-членов и методов-членов.

Характеристики:

  1. Класс, который он модифицирует, не может быть унаследован.
  2. Переменная-член, которую он модифицирует, является константой.
  3. Метод-член, который он модифицирует, не может быть переопределён подклассами.

Константы, модифицированные final, обычно имеют соглашения об именовании. Для констант, модифицированных final, все буквызаглавные.。

Переменная-член, модифицированная final, должна быть инициализирована. Есть два способа её инициализировать:

  • Явная инициализация;
  • Инициализация в конструкторе.
    Но эти два способа нельзя использовать вместе для инициализации.

Разница между final и private:

  1. Класс, модифицированный final, доступен;
    private не может модифицировать внешние классы, но может модифицировать внутренние классы (на самом деле делать внешний класс private бессмысленно).
  2. Методы, модифицированные final, не могут быть переопределены подклассами;
    Методы, модифицированные private, выглядят так, будто их можно переопределить в подклассах, но на самом деле это невозможно, потому что подклассы не видят private-методы родительского класса.
  3. Переменная, модифицированная 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 можно определитьметоды без тела метода.Конкретную реализацию такого метода предоставляетподкласс.Неполный метод называется абстрактным методом, а класс, содержащий абстрактный метод, является абстрактным классом.

Происхождение:

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

Особенности абстрактных классов:

  1. Абстрактные методы должны находиться в абстрактном классе;
  2. И абстрактные методы, и абстрактные классы должны быть помечены ключевым словом `abstract`;
  3. Абстрактные классы не могут использовать `new` для создания объектов, потому что вызов абстрактного метода не имеет смысла;
  4. Чтобы абстрактные методы в абстрактном классе можно было использовать, подкласс должен переопределить все его абстрактные методы, а затем создать объект подкласса, чтобы вызывать их; если подкласс переопределяет только часть абстрактных методов, он всё ещё остаётся абстрактным классом;
  5. Абстрактный класс может иметь абстрактные методы или неабстрактные методы; абстрактные методы используются для создания экземпляра подкласса;
  6. Если класс является абстрактным, то наследующие его подклассы должны либо быть абстрактными классами, либо переопределить все абстрактные методы.
    Особый случай: абстрактный класс может не определять абстрактные методы; это делается только для того, чтобы запретить создание объектов этого класса.

Характеристики членов абстрактных классов:

  • Переменные-члены: могут быть переменными или константами;
  • Конструкторы: конструкторы есть;
  • Методы-члены: могут быть абстрактными или неабстрактными методами.
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`

Концептуальные характеристики интерфейсов:

  1. Интерфейс — этовнешне предоставляемыеправила;
  2. Интерфейс — этофункциональное расширение;
  3. программы;Появление интерфейсовснижает связанность; (это реализует модульную разработку: правила определены, каждый реализует свой модуль, что значительно повышает эффективность разработки)
  4. Интерфейсы могут использоваться длямножественной реализации;
  5. Нескольконесвязанных классов могут реализовывать один и тот же интерфейс;
  6. Класс может реализовыватьнесколькоинтерфейсов, не имеющих прямой связи друг с другом;
  7. Подобно отношению наследования, между интерфейсом и его классом реализации существуетполиморфизм。
//运动员和教练的案例(下图是思路分析)

/*
    篮球运动员和教练
    乒乓球运动员和教练
    现在篮球运动员和教练要出国访问,需要学习英语
    请根据你所学的知识,分析出来哪些是类,哪些是抽象类,哪些是接口
*/
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