Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

4 года назад
Открыть в
День 1306. #TypesAndLanguages 7. Инкапсуляция или Публичное Всё Сейчас немного разожгу: Всё должно быть публичным. Не используйте модификатор private вообще. А теперь давайте обсудим это немного подробнее. Одно из свойств инкапсуляции состоит в сокрытии внутреннего устройства. Это может выражаться в различных формах. Самая простая из них — геттеры и сеттеры. Мы делаем поля приватными, а затем открываем методы доступа для чтения и записи. Однако всё может быть общедоступным, и при этом мы всё равно можем скрывать внутренности. Как это возможно? Бывают ситуации, когда нам нужно получить доступ к некоторым внутренним элементам или изменить их. Либо напрямую, либо через рефлексию, либо через взлом памяти. Проблема в том, что в большинстве случаев компиляторы нам не помогут в таких ситуациях. Компиляторы не будут проверять вашу рефлексию, верна она у вас или нет. Они не остановят компиляцию вашего небезопасного низкоуровневого кода, если он неверен. Это значительно усложняет работу с внутренними компонентами, поскольку они могут быть изменены практически в любое время, а у нас нет механизма, позволяющего обнаружить, что изменение нарушает наш код. Однако такой проблемы не бывает, когда всё публично. Если вы обращаетесь к внутренним компонентам напрямую, компилятор сообщит вам, когда произойдёт критическое изменение. Это позволяет находить ошибки намного раньше и намного проще. Но как мы можем скрывать внутренности, когда всё публично? Ответ: представления. С помощью различных представлений, которые в большинстве языков реализованы через интерфейсы, мы можем предоставлять абстракцию, но по-прежнему иметь доступ к внутренним компонентам. Представьте, что у нас есть следующий класс:
class Foo {
  public void Bar() { … }
  private void BarInternals() { … }
}

Можно сказать, что это хорошо, потому что класс скрывает BarInternals, делая его приватным. Таким образом, вызывающая сторона не может получить доступ к внутренним компонентам и не нарушит их. Однако можно использовать интерфейсы:
interface IFoo {
  void Bar();
}
class Foo : IFoo {
  public void Bar() { … }
  public void BarInternals() { … }
}

Теперь любой «порядочный» клиент, вызывающий объект, должен использовать Foo через интерфейс IFoo, поэтому метод BarInternals останется недоступным. Дело не в том, что он приватный или доступ заблокирован контроллером политик. Метода просто нет! Однако, если кому-то нужно схитрить, он может привести IFoo к Foo и получить поддержку компилятора, чтобы убедиться, что BarInternals существует. Это может быть реализовано несколькими способами в разных языках: интерфейсы, заголовочные файлы, разные пакеты для абстракции и реализации. Есть несколько решений, позволяющих сделать внутреннее содержимое общедоступным. Примечание: От себя добавлю, что делать совсем всё публичным, наверное, чересчур радикально. На моей практике доступ к внутренностям нужен не так часто, поэтому такой проблемы обычно не возникает. Но в принципе, подход с сокрытием через интерфейс интересный. Что скажете? Источник: https://blog.adamfurmanek.pl/2022/07/23/types-and-programming-languages-part-16/ Автор оригинала: Adam Furmanek