Что такое концепции ООП?

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

1. Абстракция
2. Инкапсуляция
3. Наследование
4. Полиморфизм
5. Ассоциация
6. Агрегация
7. Композиция

Java поставляется со специфическими структурами кода для каждой концепции ООП, такими как ключевое слово extends для принципа наследования или методы getter и setter для принципа инкапсуляции.

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

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

Что такое концепции ООП в Java?

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

Существует четыре основных и три второстепенных принципа объектно-ориентированного программирования на Java. Давайте рассмотрим, что это такое и почему они полезны.

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

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

То же самое справедливо и для классов Java. Вы можете скрыть внутренние детали реализации, используя абстрактные классы или интерфейсы. На абстрактном уровне вам нужно только определить сигнатуры методов (имя и список параметров) и позволить каждому классу реализовать их по-своему.

Абстракция в Java:

  • Скрывает базовую сложность данных
  • Помогает избежать повторяющегося кода
  • Представляет только сигнатуру внутренней функциональности
  • Дает гибкость программистам для изменения реализации абстрактного поведения
  • Частичная абстракция (0-100%) может быть достигнута с помощью абстрактных классов
  • Полная абстракция (100%) может быть достигнута с помощью интерфейсов

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

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

Вы можете реализовать инкапсуляцию в Java, сделав поля (переменные класса) приватными и получив доступ к ним через их публичные методы getter и setter. JavaBeans являются примерами полностью инкапсулированных классов.

Инкапсуляция в Java:

  • Ограничивает прямой доступ к членам данных (полям) класса.
  • Поля имеют статус private
  • Каждое поле имеет методы getter и setter.
  • Методы getter возвращают значение поля
  • Методы setter позволяют нам изменять значение поля.

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

Наследование позволяет создать дочерний класс, который наследует поля и методы родительского класса. Дочерний класс может переопределять значения и методы родительского класса, но это не обязательно. Он также может добавлять новые данные и функциональные возможности в свой родительский класс.

Родительские классы также называют суперклассами или базовыми классами, а дочерние классы — подклассами или производными классами. Java использует ключевое слово extends для реализации принципа наследования в коде.

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

  • Класс (дочерний класс) может расширять другой класс (родительский класс), наследуя его свойства
  • Реализует принцип программирования DRY (Don’t Repeat Yourself)
  • Улучшает возможность повторного использования кода
  • Многоуровневое наследование разрешено в Java (дочерний класс может иметь свой собственный дочерний класс)
  • Множественное наследование в Java не допускается (класс не может расширять более одного класса)
  • Абстракция, инкапсуляция, полиморфизм и наследование — это четыре основных теоретических принципа объектно-ориентированного программирования. Но Java также работает с тремя другими концепциями ООП: ассоциация, агрегация и композиция. Агрегация — это особая форма ассоциации, а композиция — особая форма агрегации. Хотя это может показаться немного запутанным, мы сейчас все объясним. Читайте дальше!

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

Полиморфизм означает способность выполнять определенное действие различными способами. В Java полиморфизм может принимать две формы: перегрузка методов и переопределение методов.

Перегрузка методов происходит, когда в классе присутствуют различные методы с одинаковым именем. Когда они вызываются, их различают по количеству, порядку или типам параметров. Переопределение метода происходит, когда дочерний класс переопределяет метод своего родителя.

Полиморфизм в Java:

  • Одно и то же имя метода используется несколько раз
  • Из объекта могут быть вызваны разные методы с одинаковым именем
  • Все объекты Java можно считать полиморфными (как минимум, они имеют свой тип и являются экземплярами класса Object).
  • Статический полиморфизм в Java реализуется перегрузкой методов
  • Динамический полиморфизм в Java реализуется путем переопределения методов
  • 5. Ассоциация
  • Ассоциация означает акт установления отношений между двумя несвязанными классами. Например, когда вы объявляете два поля разных типов (например, Car и Bicycle) в одном классе и заставляете их взаимодействовать друг с другом, вы создали ассоциацию.

5. Ассоциация

Ассоциация означает акт установления отношений между двумя несвязанными классами. Например, когда вы объявляете два поля разных типов (например, Car и Bicycle) в одном классе и заставляете их взаимодействовать друг с другом, вы создали ассоциацию.

Ассоциация в Java:

  • Два отдельных класса связаны через свои объекты
  • Два класса не связаны между собой, каждый из них может существовать без другого.
  • Отношения могут быть один к одному, один ко многим, много к одному или много ко многим.

6. Агрегация

Агрегация — это более узкий вид ассоциации. Она возникает, когда между двумя классами, которые мы ассоциируем через их объекты, существует односторонняя связь (HAS-A).

Например, у каждого пассажира есть автомобиль, но у автомобиля не обязательно есть пассажир. Когда вы объявляете класс Passenger, вы можете создать поле типа Car, которое показывает, к какому автомобилю принадлежит пассажир. Затем, когда вы создаете новый объект Passenger, вы можете получить доступ к данным, хранящимся в связанном с ним Car.

Агрегация в Java:

  • Однонаправленная ассоциация
  • Представляет собой отношение HAS-A между двумя классами.
  • Только один класс зависит от другого

7. Композиция

Композиция — это более строгая форма агрегации. Она возникает, когда два класса, которые вы связываете, являются взаимозависимыми и не могут существовать друг без друга.

Например, возьмем класс «Автомобиль» и класс «Двигатель». Автомобиль не может работать без двигателя, а двигатель также не может функционировать, не будучи встроенным в автомобиль. Такие отношения между объектами также называются отношениями PART-OF.

Композиция в Java:

  • Ограниченная форма агрегации
  • Представляет собой отношение ЧАСТЬ-ОФ между двумя классами
  • Оба класса зависят друг от друга
  • Если один класс перестает существовать, другой не может выжить в одиночку.

Абстракция

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

Java предоставляет два способа реализации абстракции: абстрактные классы и интерфейсы. С помощью абстрактных классов можно добиться частичной абстракции, а интерфейсы делают возможной полную (100%) абстракцию.

Абстрактные классы
Абстрактный класс — это суперкласс (родительский класс), который не может быть инстанцирован. Чтобы создать новый объект, необходимо инстанцировать один из его дочерних классов. Абстрактные классы могут иметь как абстрактные, так и конкретные методы. Абстрактные методы содержат только сигнатуру метода, в то время как конкретные методы объявляют также тело метода. Абстрактные классы определяются с помощью ключевого слова abstract.

В приведенном ниже примере кода мы создаем абстрактный класс Animal с двумя абстрактными и одним конкретным методом.

abstract  class  Animal  {
// abstract methods
abstract  void  move();
abstract  void  eat();
// concrete method
void  label()  {
System.out.println("Animal's data:");
}
}
Вход в полноэкранный режим Выход из полноэкранного режима

Затем мы расширяем его двумя дочерними классами: Bird и Fish. Оба они определяют свои собственные реализации абстрактных методов move() и eat().

class  Bird  extends Animal {
void  move()  {
System.out.println("Moves by flying.");
}
void  eat()  {
System.out.println("Eats birdfood.");
}
}
Вход в полноэкранный режим Выйти из полноэкранного режима
class  Fish  extends Animal {
void  move()  {
System.out.println("Moves by swimming.");
}
void  eat()  {
System.out.println("Eats seafood.");
}
}
Войти в полноэкранный режим Выход из полноэкранного режима

Теперь мы протестируем его с помощью классов TestBird и TestFish. Оба инициализируют объект (myBird и myFish) и вызывают один конкретный (label()) и два абстрактных (move() и eat()) метода.

Заметьте, однако, что вам не обязательно вызывать все методы, если вы этого не хотите — таким образом абстрактные классы делают возможной частичную абстракцию (например, вы можете вызвать только move()).

class  TestBird  {
public  static  void  main(String[] args)  {
Animal myBird =  new Bird();
myBird.label();
myBird.move();
myBird.eat();
}
}
Вход в полноэкранный режим Выход из полноэкранного режима
class  TestFish  {
public  static  void  main(String[] args)  {
Animal myFish =  new Fish();
myFish.label();
myFish.move();
myFish.eat();
}
}
Войти в полноэкранный режим Выход из полноэкранного режима

Как вы можете видеть ниже, конкретный метод был вызван из абстрактного класса Animal, в то время как два абстрактных метода были вызваны из Bird и Fish соответственно.

[Console output of TestBird]
Animal's data:
Moves by flying.
Eats birdfood.
Вход в полноэкранный режим Выход из полноэкранного режима
[Console output of TestFish]
Animal's data:
Moves by swimming.
Eats seafood.
Вход в полноэкранный режим Выход из полноэкранного режима

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

С помощью инкапсуляции вы можете защитить поля класса. Для этого необходимо объявить поля как приватные и обеспечить доступ к ним с помощью методов getter и setter.

Приведенный ниже класс Animal полностью инкапсулирован. У него есть три приватных поля, и каждое из них имеет свою пару методов getter и setter.

class  Animal  {
private String name;
private  double averageWeight;
private  int numberOfLegs;

// Getter methods
public String getName()  {
return name;
}
public  double  getAverageWeight()  {
return averageWeight;
}
public  int  getNumberOfLegs()  {
return numberOfLegs;
}
// Setter methods
public  void  setName(String name)  {
this.name  = name;
}
public  void  setAverageWeight(double averageWeight)  {
this.averageWeight  = averageWeight;
}
public  void  setNumberOfLegs(int numberOfLegs)  {
this.numberOfLegs  = numberOfLegs;
}
}
Вход в полноэкранный режим Выход из полноэкранного режима

Класс TestAnimal сначала создает новый объект Animal (с именем myAnimal), затем определяет значение для каждого поля с помощью методов setter и, наконец, выводит значения с помощью методов getter.

class  TestAnimal  {
public  static  void  main(String[] args)  {
Animal myAnimal =  new Animal();
myAnimal.setName("Eagle");
myAnimal.setAverageWeight(1.5);
myAnimal.setNumberOfLegs(2);
System.out.println("Name: "  + myAnimal.getName());
System.out.println("Average weight: "  + myAnimal.getAverageWeight()  +  "kg");
System.out.println("Number of legs: "  + myAnimal.getNumberOfLegs());
}
}
Вход в полноэкранный режим Выход из полноэкранного режима

Как вы можете видеть ниже, консоль Java возвращает все значения, которые мы задали с помощью методов setter:


[Console output of TestAnimal]
Name: Eagle
Average weight: 1.5kg
Number of legs: 2
Вход в полноэкранный режим Выход из полноэкранного режима

Интерфейсы

Интерфейс — это 100% абстрактный класс. Он может иметь только статические, конечные и публичные поля и абстрактные методы. Его часто называют чертежом класса. Интерфейсы Java позволяют реализовать множественное наследование в коде, поскольку класс может реализовать любое количество интерфейсов. Классы могут обращаться к интерфейсу с помощью ключевого слова implements.

В примере мы определяем два интерфейса: Animal с двумя абстрактными методами (методы интерфейса абстрактны по умолчанию) и Bird с двумя статическими полями и абстрактным методом.


interface  Animal  {
public  void  eat();
public  void  sound();
}
Вход в полноэкранный режим Выход из полноэкранного режима
interface  Bird  {
int numberOfLegs = 2;
String outerCovering =  "feather";
public  void  fly();
}
Войти в полноэкранный режим Выход из полноэкранного режима

Класс Eagle реализует оба интерфейса. Он определяет свою собственную функциональность для трех абстрактных методов. Методы eat() и sound() взяты из класса Animal, а fly() — из Bird.

class  Eagle  implements Animal, Bird {
public  void  eat()  {
System.out.println("Eats reptiles and amphibians.");
}
public  void  sound()  {
System.out.println("Has a high-pitched whistling sound.");
}
public  void  fly()  {
System.out.println("Flies up to 10,000 feet.");
}
}
Вход в полноэкранный режим Выход из полноэкранного режима

В тестовом классе TestEagleInterfaces мы создаем новый объект Eagle (называемый myEagle) и выводим все поля и методы на консоль.

Поскольку статические поля (numberOfLegs и outerCovering) принадлежат не конкретному объекту, а интерфейсу, нам нужно обращаться к ним из интерфейса Bird, а не из объекта myEagle.

class  TestEagleInterfaces  {
public  static  void  main(String[] args)  {
Eagle myEagle =  new Eagle();

myEagle.eat();
myEagle.sound();
myEagle.fly();

System.out.println("Number of legs: "  + Bird.numberOfLegs);
System.out.println("Outer covering: "  + Bird.outerCovering);
}
}
Вход в полноэкранный режим Выход из полноэкранного режима

Java-консоль возвращает всю информацию, к которой мы хотели получить доступ:

[Console output of TestEagleInterfaces]
Eats reptiles and amphibians.
Has a high-pitched whistling sound.
Flies up to 10,000 feet.
Number of legs: 2
Outer covering: feather
Вход в полноэкранный режим Выход из полноэкранного режима

Полиморфизм

Полиморфизм позволяет использовать одну и ту же структуру кода в разных формах. В Java это означает, что вы можете объявить несколько методов с одинаковым именем, если они отличаются по определенным характеристикам.

Как упоминалось выше, Java предоставляет два способа реализации полиморфизма: перегрузка методов и переопределение методов.

Статический полиморфизм (перегрузка методов)
Перегрузка методов означает, что в классе можно иметь несколько методов с одинаковым именем. Однако количество, имена или типы их параметров должны быть разными.

Например, в классе Bird(), представленном ниже, есть три метода fly(). Первый из них не имеет параметров, второй имеет один параметр (высота), а третий — два параметра (имя и высота).

class  Bird  {
public  void  fly()  {
System.out.println("The bird is flying.");
}
public  void  fly(int height)  {
System.out.println("The bird is flying "  + height +  " feet high.");
}
public  void  fly(String name,  int height)  {
System.out.println("The "  + name +  " is flying "  + height +  " feet high.");
}
}
Вход в полноэкранный режим Выход из полноэкранного режима

Тестовый класс создает новый объект Bird и вызывает метод fly() три раза: первый — без параметров, второй — с одним целочисленным параметром высоты и третий — с двумя параметрами имени и высоты.

class  TestBirdStatic  {
public  static  void  main(String[] args)  {
Bird myBird =  new Bird();
myBird.fly();
myBird.fly(10000);
myBird.fly("eagle", 10000);
}
}
Вход в полноэкранный режим Выход из полноэкранного режима

В консоли видно, что Java могла бы различать три полиморфных метода fly():

[Console output of TestBirdStatic]
The bird is flying.
The bird is flying 10000 feet high.
The eagle is flying 10000 feet high.
Войти в полноэкранный режим Выход из полноэкранного режима

Динамический полиморфизм (переопределение методов)

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

В приведенном ниже примере кода класс Bird расширяет класс Animal. Оба класса имеют метод eat(). По умолчанию Bird наследует метод eat() своего родителя. Однако, поскольку она также определяет свой собственный метод eat(), Java переопределит исходный метод и вызовет eat() из дочернего класса.

class  Animal  {
public  void  eat()  {
System.out.println("This animal eats insects.");
}
}
Вход в полноэкранный режим Выход из полноэкранного режима
class  Bird  extends Animal {
public  void  eat()  {
System.out.println("This bird eats seeds.");
}
}
Вход в полноэкранный режим Выход из полноэкранного режима

Класс TestBirdDynamic сначала создает новый объект Animal и вызывает его метод eat(). Затем он также создает объект Bird и снова вызывает полиморфный метод eat().

class  TestBirdDynamic  {
public  static  void  main(String[] args)  {
Animal myAnimal =  new Animal();
myAnimal.eat();
Bird myBird =  new Bird();
myBird.eat();
}
}
Вход в полноэкранный режим Выход из полноэкранного режима

Консоль правильно возвращает значения соответствующих методов, потому что Java могла бы различать два метода eat():

[Console output of TestBirdDynamic]
This animal eats insects.
This bird eats seeds.
Войти в полноэкранный режим Выход из полноэкранного режима

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

Резюме

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

Оцените статью
devanswers.ru
Добавить комментарий