← Назад к вопросам

Как использовать полиморфизм для управления объектами?

1.0 Junior🔥 91 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Полиморфизм в Java для управления объектами

Полиморфизм — один из четырёх столпов ООП, позволяет работать с объектами разных типов через единый интерфейс. Это мощный инструмент для создания гибкого и расширяемого кода.

1. Полиморфизм через наследование

Работаем с объектами разных типов как с объектом базового класса:

public abstract class Animal {
    public abstract void makeSound();
    public abstract void move();
    
    public void sleep() {
        System.out.println("Zzz...");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
    
    @Override
    public void move() {
        System.out.println("Running on 4 legs");
    }
}

public class Bird extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Tweet tweet!");
    }
    
    @Override
    public void move() {
        System.out.println("Flying");
    }
}

public class Fish extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Blub blub");
    }
    
    @Override
    public void move() {
        System.out.println("Swimming");
    }
}

// Использование полиморфизма
List<Animal> animals = new ArrayList<>();
animals.add(new Dog());
animals.add(new Bird());
animals.add(new Fish());

for (Animal animal : animals) {
    animal.makeSound();  // Вызовет метод конкретного класса
    animal.move();
    animal.sleep();      // Используют одну реализацию
}

2. Полиморфизм через интерфейсы

Более гибкий способ — использование интерфейсов:

public interface PaymentProcessor {
    void processPayment(BigDecimal amount);
    void refund(BigDecimal amount);
}

public class CreditCardProcessor implements PaymentProcessor {
    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("Processing credit card payment: " + amount);
        validateCard();
        chargeCard(amount);
    }
    
    @Override
    public void refund(BigDecimal amount) {
        System.out.println("Refunding credit card: " + amount);
    }
}

public class PayPalProcessor implements PaymentProcessor {
    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("Processing PayPal payment: " + amount);
        validateAccount();
        transferFunds(amount);
    }
    
    @Override
    public void refund(BigDecimal amount) {
        System.out.println("Refunding PayPal: " + amount);
    }
}

public class StripeProcessor implements PaymentProcessor {
    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("Processing Stripe payment: " + amount);
        callStripeAPI(amount);
    }
    
    @Override
    public void refund(BigDecimal amount) {
        System.out.println("Refunding Stripe: " + amount);
    }
}

// Использование
public class PaymentService {
    private PaymentProcessor processor;
    
    public PaymentService(PaymentProcessor processor) {
        this.processor = processor;
    }
    
    public void checkout(BigDecimal amount) {
        processor.processPayment(amount);
    }
    
    public void cancelOrder(BigDecimal amount) {
        processor.refund(amount);
    }
}

// В приложении
PaymentProcessor processor = new CreditCardProcessor();
PaymentService service = new PaymentService(processor);
service.checkout(new BigDecimal("99.99"));

3. Полиморфизм с типами данных

Обработка коллекций разных типов через один код:

public interface DataStore {
    void save(String key, Object value);
    Object retrieve(String key);
}

public class MapDataStore implements DataStore {
    private Map<String, Object> data = new HashMap<>();
    
    @Override
    public void save(String key, Object value) {
        data.put(key, value);
    }
    
    @Override
    public Object retrieve(String key) {
        return data.get(key);
    }
}

public class RedisDataStore implements DataStore {
    @Override
    public void save(String key, Object value) {
        redisClient.set(key, value);
    }
    
    @Override
    public Object retrieve(String key) {
        return redisClient.get(key);
    }
}

public class CacheManager {
    private DataStore store;
    
    public CacheManager(DataStore store) {
        this.store = store;
    }
    
    public void cacheUser(User user) {
        store.save("user_" + user.getId(), user);
    }
    
    public User getUser(Long id) {
        return (User) store.retrieve("user_" + id);
    }
}

4. Стратегический паттерн (Strategy Pattern)

Полиморфизм для выбора алгоритма в runtime:

public interface SortingStrategy {
    void sort(int[] array);
}

public class QuickSort implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        quickSort(array, 0, array.length - 1);
    }
}

public class MergeSort implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        mergeSort(array, 0, array.length - 1);
    }
}

public class BubbleSort implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        bubbleSort(array);
    }
}

public class Sorter {
    private SortingStrategy strategy;
    
    public void setStrategy(SortingStrategy strategy) {
        this.strategy = strategy;
    }
    
    public void execute(int[] array) {
        strategy.sort(array);
    }
}

// Использование
Sorter sorter = new Sorter();

// Для малого массива используем BubbleSort
sorter.setStrategy(new BubbleSort());
sorter.execute(smallArray);

// Для большого массива переключаемся на QuickSort
sorter.setStrategy(new QuickSort());
sorter.execute(largeArray);

5. Фабрики и полиморфизм

Полиморфизм упрощает работу с фабриками:

public interface NotificationSender {
    void send(String message, String recipient);
}

public class EmailNotification implements NotificationSender {
    @Override
    public void send(String message, String recipient) {
        emailService.sendEmail(recipient, message);
    }
}

public class SmsNotification implements NotificationSender {
    @Override
    public void send(String message, String recipient) {
        smsService.sendSms(recipient, message);
    }
}

public class PushNotification implements NotificationSender {
    @Override
    public void send(String message, String recipient) {
        pushService.sendPush(recipient, message);
    }
}

public class NotificationFactory {
    public static NotificationSender create(NotificationType type) {
        return switch(type) {
            case EMAIL -> new EmailNotification();
            case SMS -> new SmsNotification();
            case PUSH -> new PushNotification();
            default -> throw new IllegalArgumentException("Unknown type");
        };
    }
}

public class NotificationService {
    public void notifyUser(User user, String message, NotificationType type) {
        NotificationSender sender = NotificationFactory.create(type);
        sender.send(message, user.getContact(type));
    }
}

6. Практический пример: система отчётов

public interface Report {
    void generate();
    byte[] export(String format);
}

public class SalesReport implements Report {
    @Override
    public void generate() {
        System.out.println("Generating sales data...");
    }
    
    @Override
    public byte[] export(String format) {
        return switch(format) {
            case "PDF" -> generatePDF();
            case "EXCEL" -> generateExcel();
            case "CSV" -> generateCSV();
            default -> new byte[0];
        };
    }
}

public class InventoryReport implements Report {
    @Override
    public void generate() {
        System.out.println("Generating inventory data...");
    }
    
    @Override
    public byte[] export(String format) {
        return switch(format) {
            case "PDF" -> generatePDF();
            case "EXCEL" -> generateExcel();
            default -> new byte[0];
        };
    }
}

public class ReportGenerator {
    private Report report;
    
    public ReportGenerator(Report report) {
        this.report = report;
    }
    
    public void scheduleGeneration() {
        report.generate();
    }
    
    public void exportAs(String format) {
        byte[] data = report.export(format);
        saveToFile(data, format);
    }
}

Преимущества полиморфизма

  1. Расширяемость — легко добавлять новые реализации без изменения существующего кода
  2. Гибкость — можно менять поведение в runtime
  3. Переиспользуемость — один код работает с разными типами
  4. Упрощение — меньше if-else и type checking
  5. Тестируемость — легче мокировать зависимости

Лучшие практики

  1. Используй интерфейсы вместо конкретных классов в параметрах
  2. Зависи от абстракций, не от реализаций (Dependency Inversion Principle)
  3. Выбирай интерфейсы для новых дизайнов, наследование для расширения существующих
  4. Не переусложняй с глубокой иерархией классов
  5. Используй полиморфизм для повышения гибкости, а не для сложности
Как использовать полиморфизм для управления объектами? | PrepBro