Модификаторы доступа и Наследование

JavaJavaBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

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


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("Classes/Objects") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/class_attributes("Class Attributes") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/class_methods("Class Methods") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/constructors("Constructors") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/modifiers("Modifiers") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/inheritance("Inheritance") subgraph Lab Skills java/classes_objects -.-> lab-178543{{"Модификаторы доступа и Наследование"}} java/class_attributes -.-> lab-178543{{"Модификаторы доступа и Наследование"}} java/class_methods -.-> lab-178543{{"Модификаторы доступа и Наследование"}} java/constructors -.-> lab-178543{{"Модификаторы доступа и Наследование"}} java/modifiers -.-> lab-178543{{"Модификаторы доступа и Наследование"}} java/inheritance -.-> lab-178543{{"Модификаторы доступа и Наследование"}} end

Модификаторы доступа

На данный момент мы уже написали некоторый код. В предыдущей лабораторной работе мы написали класс. Есть некоторые модификаторы, такие как public и private. Так, что означают эти слова?

Java предоставляет ряд модификаторов доступа для установки уровней доступа для классов, переменных, методов и конструкторов. Четыре уровня доступа следующие:

  • default: Видимый внутри пакета, стандартный. Не требуется никаких модификаторов.
  • private: Видимый только для определяющего класса.
  • public: Видимый для всего Java-мира (всех типов). Его можно использовать в любом месте.
  • protected: Видимый для пакета и всех подклассов (даже для подклассов из других пакетов).
Диаграмма модификаторов доступа в Java

Java предоставляет ряд не-модификаторов доступа для достижения многих других способов тонкой настройки поведения:

  • static: Этот модификатор используется для создания переменных или методов, которые будут существовать независимо от любых экземпляров класса. Для класса существует только одна копия static-переменной независимо от количества созданных экземпляров.
  • final: final-переменная может быть явно инициализирована только один раз. final-метод не может быть переопределен любыми подклассами. Класс объявляется как final, чтобы предотвратить его наследование.
  • abstract: abstract-класс никогда не может быть инстанциирован. abstract-метод - это метод, объявленный без какой-либо реализации.
  • synchronized/volatile: Модификаторы synchronized и volatile используются в связке с потоками.

Пример:

Напишите следующий код в файле /home/labex/project/modifierTest.java:

public class modifierTest {
    // static variables are initialized when class is loaded.
    public static int i = 10;
    public static final int NUM = 5;
    // non-static variables are initialized when object is created.
    public int j = 1;

    /*
     * static code block here, this will execute when the class is loaded
     * creating new object will not execute the block again, run only once.
    */
    static{
        System.out.println("this is a class static block.");
    }
    public static void main(String[] args)
    {
        System.out.println("this is in main method");

        // you can access i and change it
        modifierTest.i = 20;  //the same with obj.i = 20
        System.out.println("Class variable i = " + modifierTest.i);
        // you can access NUM, but can't change it
        // HelloWorld.NUM = 10;     this will cause an error, NUM is final, it's immutable
        System.out.println("Class variable NUM = " + modifierTest.NUM);

        // create new object
        modifierTest obj = new modifierTest();
        // we can use both class and object to access static methods and static properties
        obj.staticMethod();  // the same with modifierTest.staticMethod()
        // you can't access j like this: modifierTest.j
        System.out.println("Object variable j = " + obj.j);
    }
    // the constructor, only new object being created will call this.
    public modifierTest(){
        System.out.println("this is in object's constructor.");
    }
    public static void staticMethod(){
        System.out.println("this is a static method");
    }
}

Вывод:

Запустите файл modifierTest.java с использованием следующих команд:

javac /home/labex/project/modifierTest.java
java modifierTest

Посмотрите на вывод:

this is a class static block.
this is in main method
Class variable i = 20
Class variable NUM = 5
this is in object's constructor.
this is a static method
Object variable j = 1

Наследование

В многих случаях мы пишем класс. Затем, нам нужно написать новый класс, который будет лишь немного модифицировать код предыдущего класса, и они имеют некоторое логическое отношение. Здесь мы можем использовать наследование. Мы используем ключевое слово extends для реализации наследования. Подклассы наследуют все доступные свойства и методы суперкласса, и подклассы могут иметь и свои собственные особые свойства. В подклассах мы можем обращаться к тем, что объявлено в суперклассе как public или protected, но private свойства напрямую не доступны. См. пример: Структура наследования показана на рисунке. Вы можете реализовать многоуровневое наследование (горизонтальное) или иерархическое наследование (вертикальное):

Диаграмма структуры наследования

Пример:

Напишите следующий код в файле /home/labex/project/inheritanceTest.java:

class Animal{
    // Какой я вид животного.
    private String species;
    private int age = 8;

    public Animal(){
        System.out.println("Конструктор Animal");
    }
    public void grow(){
        // В этом классе мы можем напрямую обращаться к приватным свойствам.
        System.out.println("Мне " + this.age + " лет, " + "я расту.");
    }
}
class Dog extends Animal{
    private String color;
    // В этом классе мы не можем обращаться к приватным атрибутам суперкласса, но grow() доступен.
    public Dog(){
        System.out.println("Конструктор Dog");
    }
    public void run(){
        this.grow();
        System.out.println("Я собака, я могу бежать.");
    }
}
class Bird extends Animal{
    private double weight;

    public Bird(){
        // Если явно вызывать конструктор суперкласса, то это должно быть первой строкой здесь.
        // super();
        System.out.println("Конструктор Bird");
    }
    public void fly(){
        this.grow();
        System.out.println("Я птица, я могу летать.");
    }
}
public class inheritanceTest{
    public static void main(String[] args){
        Dog dog = new Dog();
        dog.run();

        Bird bird = new Bird();
        bird.fly();
    }
}

Вывод:

Запустите файл inheritanceTest.java с использованием следующих команд:

javac /home/labex/project/inheritanceTest.java
java inheritanceTest

Посмотрите на вывод:

Конструктор Animal
Конструктор Dog
Мне 8 лет, я расту.
Я собака, я могу бежать.
Конструктор Animal
Конструктор Bird
Мне 8 лет, я расту.
Я птица, я могу летать.

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

Обзор

С помощью модификаторов доступа мы можем писать безопасный код, скрывать детали, реализовывать контроль доступа. Другие пользователи не должны знать, как мы реализуем детали методов. Мы предоставляем интерфейс другим вызывающим сторонам. По модификаторам доступа вы можете изучить исходный код Java-библиотек, чтобы понять, в чем разница. Наследование, помните об иерархической структуре, представляет собой отношение между классами.