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

«Как реализовать интерфейс для клонирования объектов? Приведи пример на TypeScript.» — вопрос из категории Основы программирования, который задают на 10% собеседований QA Тестировщик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для создания копий объектов используется шаблон Прототип (Prototype), который можно выразить через интерфейс с методом clone().

Пример интерфейса Cloneable и его реализации:

// Обобщенный (generic) интерфейс для клонирования
interface Cloneable<T> {
  clone(): T;
}

// Класс, реализующий интерфейс. Важно создать глубокую (deep) копию.
class UserSettings implements Cloneable<UserSettings> {
  constructor(
    public theme: string,
    public notificationsEnabled: boolean,
    public preferences: string[] // Массив - ссылочный тип!
  ) {}

  // Метод clone() создает новый независимый объект
  clone(): UserSettings {
    // Глубокая копия для корректного клонирования ссылочных типов
    return new UserSettings(
      this.theme, // Примитив - копируется по значению
      this.notificationsEnabled, // Примитив
      [...this.preferences] // Создаем КОПИЮ массива
    );
  }
}

// Пример использования
const originalSettings = new UserSettings('dark', true, ['email', 'sms']);
const clonedSettings = originalSettings.clone();

// Меняем клон
clonedSettings.theme = 'light';
clonedSettings.preferences.push('push');

console.log(originalSettings.theme); // 'dark' (оригинал не изменился)
console.log(originalSettings.preferences); // ['email', 'sms'] (оригинальный массив не изменился!)
console.log(clonedSettings.preferences); // ['email', 'sms', 'push']

Ключевые моменты:

  • Интерфейс Cloneable<T> задает контракт для любых клонируемых объектов.
  • Глубокая копия (Deep Copy): Критически важно корректно копировать вложенные объекты и массивы (используем spread оператор [...] или Array.from()). Поверхностное копирование приведет к тому, что клон и оригинал будут разделять ссылки на одни и те же вложенные объекты.
  • Применение: Полезно для создания снимков (snapshots) состояния, отката изменений или работы с объектами, которые не должны меняться после передачи в другие части системы.