🧑‍🏫10. Инкапсуляция

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

Зачем нужна инкапсуляция?

  1. Защищает данные: предотвращает случайные или неправильные изменения данных извне.

  2. Упрощает использование: делает объекты проще и понятнее для других частей программы.

  3. Сохраняет стабильность кода: позволяет менять внутреннюю реализацию без изменения внешнего интерфейса, что уменьшает риск поломок.

Как создавать инкапсуляцию в Dart

  1. Использование приватных переменных и методов — в Dart переменные и методы становятся приватными, если их имя начинается с _ (например, _balance).

  2. Методы для доступа к данным (геттеры и сеттеры): создаем публичные методы, чтобы безопасно читать и изменять приватные переменные.

Примеры с аналогиями

  1. Банковский счёт

    • Мы можем создать класс BankAccount, где баланс (_balance) скрыт от внешнего мира.

    • Для доступа есть методы deposit() и withdraw(), через которые можно добавлять или снимать деньги, проверяя корректность данных (например, не позволять снять больше, чем на счёте).

    class BankAccount {
      double _balance = 0; // приватная переменная
    
      void deposit(double amount) {
        if (amount > 0) {
          _balance += amount;
        }
      }
    
      void withdraw(double amount) {
        if (amount > 0 && amount <= _balance) {
          _balance -= amount;
        }
      }
    
      double get balance => _balance; // геттер для доступа к балансу
    }

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

  2. Телефон

    • В классе Phone можно скрыть сложные внутренние процессы, такие как проверка заряда батареи и соединение с сетью.

    • При этом мы оставляем доступ к публичным методам makeCall() или sendMessage(), которые работают независимо от внутреннего устройства телефона.

    class Phone {
      bool _isCharged = true; // приватная переменная
      
      void makeCall(String number) {
        if (_isCharged) {
          print('Звоним на $number');
        } else {
          print('Батарея разряжена');
        }
      }
    }
  3. Машина

    • В классе Car скрываем двигатель и топливную систему, которые не видны пользователю.

    • Публичный метод drive() позволяет пользователю ехать, но не требует знания о том, как работают двигатель или трансмиссия.

    class Car {
      bool _engineRunning = false; // приватное состояние двигателя
      
      void startEngine() {
        _engineRunning = true;
      }
    
      void drive() {
        if (_engineRunning) {
          print('Машина едет');
        } else {
          print('Сначала запустите двигатель');
        }
      }
    }

    Аналогия: Это как педали и руль, которые управляют машиной, не раскрывая детали того, как работает двигатель.

  4. Робот-пылесос

    • В классе RobotVacuum можно скрыть логику передвижения и сенсоры, чтобы пользователь мог просто использовать метод startCleaning().

    class RobotVacuum {
      bool _isBatteryCharged = true;
      
      void startCleaning() {
        if (_isBatteryCharged) {
          print('Начинаю уборку');
        } else {
          print('Нужно зарядить батарею');
        }
      }
    }

    Аналогия: Представьте, что робот-пылесос просто "убирается", и мы не видим, как он определяет, где грязь, а где чисто.

  5. Электронная книга

    • В классе EBookReader скрыты сложные процессы обработки и отображения текста.

    • У пользователя есть публичные методы openBook() и turnPage(), чтобы читать книгу без вмешательства в детали работы программы.

    class EBookReader {
      String _bookContent = "Содержание книги...";
    
      void openBook() {
        print("Книга открыта");
      }
    
      void turnPage() {
        print("Переворачиваем страницу");
      }
    }

    Аналогия: Электронная книга позволяет читать текст, не раскрывая, как устройство обрабатывает и отображает данные.

Резюме

Инкапсуляция помогает:

  • Скрывать внутренние данные и процессы, предоставляя только нужные методы.

  • Защищать данные и создавать единый интерфейс, которым легко пользоваться.

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

Пример:

Создадим мини-приложение для управления профилем пользователя. В этом приложении будет инкапсулирована информация о пользователе, такая как имя, возраст и email. Мы будем использовать инкапсуляцию, чтобы скрыть эти данные от прямого доступа и предоставить методы для их безопасного изменения и получения.

Почему использовать инкапсуляцию?

Инкапсуляция позволяет:

  1. Защищать данные: Мы можем контролировать, как данные изменяются, например, проверять, чтобы возраст был положительным, а email соответствовал определённому формату.

  2. Упрощать использование: Публичные методы делают взаимодействие с данными понятным и безопасным, не позволяя другим частям программы неправильно изменять внутреннее состояние объекта.

  3. Сохранять целостность данных: Мы можем изменять внутреннюю реализацию без необходимости обновлять код, который использует эти объекты.

Структура приложения

  1. Класс UserProfile — инкапсулирует данные о пользователе.

  2. Публичные методы — позволяют безопасно изменять и получать данные.

  3. Экран профиля — демонстрирует использование класса UserProfile и взаимодействие с ним.

Код приложения

Объяснение кода

  1. Класс UserProfile:

    • Инкапсуляция данных: Приватные переменные _name, _age и _email скрывают внутренние данные пользователя. Это предотвращает случайное или неправильное изменение этих данных.

    • Геттеры и сеттеры: Публичные методы get name, get age и get email позволяют безопасно получать данные. Методы setName, setAge и setEmail предоставляют контролируемый доступ для изменения этих данных с проверкой правильности (например, положительный возраст и корректный email).

  2. Экран профиля (ProfileScreen):

    • Создаёт экземпляр UserProfile и предоставляет текстовые поля для ввода нового имени, возраста и email.

    • Кнопка "Обновить профиль" вызывает сеттеры, чтобы обновить данные пользователя. Если введенные данные некорректны, это обрабатывается в сеттерах, а пользователю не нужно беспокоиться о деталях проверки.

Аналогия

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

Заключение

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

Last updated