Какие знаешь принципы ООП

«Какие знаешь принципы ООП» — вопрос из категории ООП, который задают на 35% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В контексте JavaScript и Node.js, который поддерживает ООП через классы (синтаксический сахар над прототипами), я применяю четыре основных принципа:

  1. Инкапсуляция: Сокрытие внутреннего состояния объекта и предоставление контролируемого интерфейса. В современных JS/Node.js это реализуется через приватные поля (#) и геттеры/сеттеры.

    class Logger {
      #logLevel = 'INFO'; // Приватное поле
    
      set logLevel(level) {
        if (['DEBUG', 'INFO', 'ERROR'].includes(level)) {
          this.#logLevel = level;
        }
      }
    
      log(message) {
        console.log(`[${this.#logLevel}] ${message}`);
      }
    }
  2. Наследование: Создание нового класса на основе существующего для повторного использования кода.

    class BaseService {
      constructor(dbClient) {
        this.db = dbClient;
      }
      validate() { /* общая логика */ }
    }
    
    class UserService extends BaseService {
      constructor(dbClient, emailService) {
        super(dbClient); // Вызов конструктора родителя
        this.emailService = emailService;
      }
      async createUser(data) {
        this.validate(data); // Использование метода родителя
        // ... специфичная логика
      }
    }
  3. Полиморфизм: Возможность объектов с одинаковым интерфейсом иметь разную реализацию. Часто используется с наследованием или интерфейсами.

    class CacheProvider {
      get(key) { throw new Error('Not implemented'); }
    }
    
    class RedisCache extends CacheProvider {
      get(key) { /* логика получения из Redis */ }
    }
    
    class MemoryCache extends CacheProvider {
      get(key) { /* логика получения из памяти */ }
    }
    // Один интерфейс, разные реализации
    const cache = process.env.USE_REDIS ? new RedisCache() : new MemoryCache();
    const data = await cache.get('user:123');
  4. Абстракция: Моделирование ключевых характеристик сущности, скрывая сложные детали реализации.

    // Абстракция "Отправка уведомления"
    class NotificationSender {
      send(user, message) {
        // Абстрактный метод, детали в подклассах
        throw new Error('Method send() must be implemented');
      }
    }
    // Конкретные реализации скрывают детали (SMTP, API push-сервиса и т.д.)
    class EmailSender extends NotificationSender { /* ... */ }
    class PushSender extends NotificationSender { /* ... */ }

Видео-ответы