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 class Car {
// ...
private int speed;
public int getSpeed() {
return color;
}
public void setSpeed(int speed) {
this.speed = speed;
}
// ...
}
Здесь скорость
поля инкапсулируется с помощью модификатора закрытого
доступа, и доступ к ней возможен только с помощью общедоступных методов getSpeed()
и setSpeed()
. Подробнее о модификаторах доступа можно прочитать в нашей статье о модификаторах доступа .
6. Наследование
Наследование — это механизм, который позволяет одному классу приобретать все свойства другого класса путем наследования класса. Мы называем наследующий класс дочерним классом, а унаследованный класс — суперклассом или родительским классом.
В Java мы делаем это, расширяя родительский класс. Таким образом, дочерний класс получает все свойства от родителя:
public class Car extends Vehicle {
//...
}
Когда мы расширяем класс, мы формируем отношение 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
}
}
Тип автомобиля Car
теперь будет наследоваться от родительского класса Vehicle :
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
}
}
Здесь ArmouredCar
расширяет Car
, а Car
расширяет Vehicle
. Таким образом, ArmouredCar
наследует свойства как от Car
, так и от Vehicle
.
Хотя мы наследуем от родительского класса, разработчик также может переопределить реализацию метода от родителя. Это называется переопределением метода .
В приведенном выше примере класса 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";
}
}
Дочерний класс может расширить класс GenericFile
и переопределить метод 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 .