Рубрики
Без рубрики

Концепции объектно-ориентированного программирования в Java

Краткий и практический обзор концепций ООП в Java.

Автор оригинала: Dhrubajyoti Bhattacharjee.

1. Обзор

В этой статье мы рассмотрим концепции объектно-ориентированного программирования (ООП) в Java. Мы обсудим классы, объекты, абстракцию, инкапсуляцию, наследование и полиморфизм .

2. Классы

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

Мы будем использовать конструктор для создания объектов класса:

public class Car {
 
    // member fields
    private String type;
    private String model;
    private String color;
    private int speed;
 
    // constructor
    public Car(String type, String model, String color) {
        this.type = type;
        this.model = model;
        this.color = color;
    }
     
    // member methods
    public int increaseSpeed(int increment) {
        this.speed = this.speed + increment;
        return this.speed;
    }
     
    // ...
}

Обратите внимание, что класс может иметь несколько конструкторов. Мы можем прочитать больше о классах в нашей статье о классах.

3. Объекты

Объекты создаются из классов и называются экземплярами класса. Мы создаем объекты из классов, используя их конструкторы:

Car veyron = new Car("Bugatti", "Veyron", "crimson");
Car corvette = new Car("Chevrolet", "Corvette", "black");

Здесь мы создали два экземпляра класса Car. Подробнее о них читайте в нашей статье объекты.

4. Абстракция

Абстракция скрывает сложности реализации и раскрывает более простые интерфейсы.

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

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

Мы можем прочитать больше об абстракции в наших статьях об абстрактных классах и интерфейсах.

5. Инкапсуляция

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

Например, поля-члены в классе скрыты от других классов, и к ним можно получить доступ с помощью методов-членов. Один из способов сделать это-сделать все поля данных закрытыми и доступными только с помощью методов public member:

public class Car {

    // ...
    private int speed;

    public int getSpeed() {
        return color;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }
    // ...
}

Здесь поле speed инкапсулируется с помощью модификатора private access и может быть доступно только с помощью методов public getSpeed() и setSpeed () . Мы можем прочитать больше о модификаторах доступа в нашей статье модификаторы доступа|/.

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

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

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

public class Car extends Vehicle { 
    //...
}

Когда мы расширяем класс, мы формируем отношение IS-A . Автомобиль IS-A Транспортное средство . Таким образом, он обладает всеми характеристиками Транспортного средства .

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

Чтобы облегчить работу, мы можем объединить общие функции и свойства всех типов транспортных средств в модуль (класс в случае Java). И мы можем позволить отдельным типам наследовать и повторно использовать эти свойства:

public class Vehicle {
    private int wheels;
    private String model;
    public void start() {
        // the process of starting the vehicle
    }
    
    public void stop() {
        // process to stop the vehicle
    }
    
    public void honk() { 
        // produces a default honk 
    }

}

Тип транспортного средства Автомобиль теперь наследуется от родительского Транспортного средства класса:

public class Car extends Vehicle {
    private int numberOfGears;

    public void openDoors() {
        // process to open the doors
    }
}

Java поддерживает одноуровневое и многоуровневое наследование. Это означает, что класс не может расширяться непосредственно из нескольких классов, но он может использовать иерархию:

public class ArmoredCar extends Car {
    private boolean bulletProofWindows;
    
    public void remoteStartCar() {
        // this vehicle can be started by using a remote control
    }
}

Здесь Бронированный автомобиль расширяет Автомобиль , и Автомобиль расширяет Транспортное средство . Таким образом, Бронированный автомобиль наследует свойства как от Автомобиля , так и от Транспортного средства .

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

В приведенном выше примере класса Vehicle есть метод honk () . Класс Car , расширяющий класс Vehicle , может переопределить этот метод и реализовать его так, как он хочет произвести сигнал:

public class Car extends Vehicle {  
    //...

    @Override
    public void honk() { 
        // produces car-specific honk 
    }
 }

Обратите внимание, что это также называется полиморфизмом времени выполнения, как описано в следующем разделе. Мы можем прочитать больше о наследовании в наших статьях о наследовании Java, наследовании и композиции.

7. Полиморфизм

Полиморфизм-это способность языка ООП обрабатывать данные по-разному в зависимости от их типов входных данных. В Java это может быть одно и то же имя метода, имеющее разные сигнатуры метода и выполняющее разные функции:

public class TextFile extends GenericFile {
    //...
 
    public String read() {
        return this.getContent()
          .toString();
    }
 
    public String read(int limit) {
        return this.getContent()
          .toString()
          .substring(0, limit);
    }
 
    public String read(int start, int stop) {
        return this.getContent()
          .toString()
          .substring(start, stop);
    }
}

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

Существует также время выполнения или динамический полиморфизм, когда дочерний класс переопределяет родительский метод :

public class GenericFile {
    private String name;
 
    //...
 
    public String getFileInfo() {
        return "Generic File Impl";
    }
}

Дочерний класс может расширить класс Generic File и переопределить метод GetFileInfo() :

public class ImageFile extends GenericFile {
    private int height;
    private int width;
 
    //... getters and setters
     
    public String getFileInfo() {
        return "Image File Impl";
    }
}

Подробнее о полиморфизме читайте в нашей статье “полиморфизм в Java”.

8. Заключение

В этой статье мы узнали об основных фундаментальных концепциях ООП с Java.

Примеры кода в этой статье доступны на Github .