131 lines
7.7 KiB
Markdown
131 lines
7.7 KiB
Markdown
|
---
|
|||
|
aliases:
|
|||
|
tags:
|
|||
|
- maturity/🌱
|
|||
|
date: 2024-09-27
|
|||
|
zero-link:
|
|||
|
- "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
|
|||
|
parents:
|
|||
|
- "[[ООП]]"
|
|||
|
linked:
|
|||
|
---
|
|||
|
Полиморфизм — это один из фундаментальных принципов [[ООП|объектно-ориентированного программирования]] (ООП), который позволяет объектам разных классов обрабатывать одно и то же сообщение (вызов метода) по-разному. Это делает код более гибким и расширяемым, упрощая добавление новых возможностей без изменения существующего кода.
|
|||
|
## Основные виды полиморфизма
|
|||
|
**Полиморфизм времени компиляции (статический)**: Это форма полиморфизма, которая определяется на этапе компиляции программы. Примеры включают **перегрузку методов** и **перегрузку операторов**.
|
|||
|
|
|||
|
Один и тот же метод может иметь несколько версий, которые различаются по количеству или типам параметров.
|
|||
|
|
|||
|
Пример перегрузки метода:
|
|||
|
```java
|
|||
|
public class MathOperations {
|
|||
|
public int add(int a, int b) {
|
|||
|
return a + b;
|
|||
|
}
|
|||
|
|
|||
|
public double add(double a, double b) {
|
|||
|
return a + b;
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**Полиморфизм времени выполнения (динамический)**: Это форма полиморфизма, которая проявляется на этапе выполнения программы. Здесь используется **наследование** и **переопределение методов**.
|
|||
|
|
|||
|
Полиморфизм времени выполнения позволяет классу, наследующему методы базового класса, предоставлять свою собственную реализацию этих методов.
|
|||
|
|
|||
|
Пример динамического полиморфизма:
|
|||
|
```java
|
|||
|
public class Animal {
|
|||
|
public void makeSound() {
|
|||
|
System.out.println("Animal makes sound");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class Dog extends Animal {
|
|||
|
@Override
|
|||
|
public void makeSound() {
|
|||
|
System.out.println("Dog barks");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class Cat extends Animal {
|
|||
|
@Override
|
|||
|
public void makeSound() {
|
|||
|
System.out.println("Cat meows");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class Main {
|
|||
|
public static void main(String[] args) {
|
|||
|
Animal myAnimal = new Dog(); // Полиморфизм
|
|||
|
myAnimal.makeSound(); // Вывод: Dog barks
|
|||
|
|
|||
|
myAnimal = new Cat();
|
|||
|
myAnimal.makeSound(); // Вывод: Cat meows
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## Преимущества полиморфизма
|
|||
|
- **Гибкость кода**: Полиморфизм позволяет работать с объектами через абстракции (интерфейсы или базовые классы), что делает систему гибкой для расширений и изменений. Например, новый класс может быть добавлен без изменения существующих классов или логики.
|
|||
|
- **Упрощённое управление**: Код становится более управляемым и понятным, поскольку можно использовать общие типы данных (например, интерфейсы) для работы с разными реализациями.
|
|||
|
- **Повторное использование кода**: Полиморфизм способствует использованию общих базовых классов, что уменьшает дублирование и увеличивает повторное использование кода.
|
|||
|
|
|||
|
## Частые ошибки при использовании полиморфизма
|
|||
|
- **Избыточное использование полиморфизма**: Когда полиморфизм используется там, где он не нужен, это может усложнить код. Например, создание слишком большого количества наследников для решения простой задачи.
|
|||
|
- **Нарушение принципа подстановки Лисков**: Это принцип гласит, что объект подкласса должен корректно заменять объект родительского класса без изменения поведения программы. Если полиморфизм реализован неправильно, это может привести к неожиданным ошибкам.
|
|||
|
- **Неправильное управление зависимостями**: Если базовые классы слишком зависят от подклассов или знают о специфике их реализации, это может разрушить архитектуру. Полиморфизм должен использоваться вместе с инверсией зависимостей для минимизации связности.
|
|||
|
## Пример полиморфизма
|
|||
|
Представьте, что у вас есть система для обработки платежей, которая поддерживает разные способы оплаты: кредитные карты, PayPal, банковские переводы. В этом случае вы можете создать абстрактный класс или интерфейс `PaymentMethod`, а затем реализовать его для каждого конкретного метода оплаты:
|
|||
|
|
|||
|
```java
|
|||
|
public interface PaymentMethod {
|
|||
|
void pay(double amount);
|
|||
|
}
|
|||
|
|
|||
|
public class CreditCard implements PaymentMethod {
|
|||
|
@Override
|
|||
|
public void pay(double amount) {
|
|||
|
System.out.println("Paid " + amount + " with Credit Card");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class PayPal implements PaymentMethod {
|
|||
|
@Override
|
|||
|
public void pay(double amount) {
|
|||
|
System.out.println("Paid " + amount + " with PayPal");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class PaymentProcessor {
|
|||
|
public void processPayment(PaymentMethod method, double amount) {
|
|||
|
method.pay(amount);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class Main {
|
|||
|
public static void main(String[] args) {
|
|||
|
PaymentProcessor processor = new PaymentProcessor();
|
|||
|
|
|||
|
PaymentMethod card = new CreditCard();
|
|||
|
PaymentMethod paypal = new PayPal();
|
|||
|
|
|||
|
processor.processPayment(card, 100);
|
|||
|
processor.processPayment(paypal, 200);
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Этот подход делает систему легко расширяемой: если нужно добавить новый способ оплаты, можно просто реализовать новый класс, не изменяя существующий код.
|
|||
|
***
|
|||
|
## Мета информация
|
|||
|
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
|||
|
**Родитель**:: [[ООП|ООП]]
|
|||
|
**Источник**::
|
|||
|
**Создана**:: [[2024-09-27]]
|
|||
|
**Автор**::
|
|||
|
### Дополнительные материалы
|
|||
|
-
|
|||
|
|
|||
|
### Дочерние заметки
|
|||
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|