Статьи

Могут ли объекты быть друзьями?

Как обсуждалось ранее , правильная инкапсуляция приводит к полному отсутствию «голых данных». Однако остается вопрос: как объекты могут взаимодействовать, если они не могут обмениваться данными? В конце концов мы должны предоставить некоторые данные, чтобы другие объекты могли их использовать, верно? Да, это правда. Тем не менее, я думаю, у меня есть решение, которое сохраняет инкапсуляцию на месте, позволяя объектам взаимодействовать.

Бешеный бык (1980) Мартина Скорсезе

Скажи, что это наш объект:

1
2
3
4
5
6
class Temperature {
  private int t;
  public String toString() {
    return String.format("%d C", this.t);
  }
}

Это представляет температуру. Единственное поведение, которое он демонстрирует, — это печать температуры в градусах Цельсия. Мы не хотим раскрывать t , потому что это приведет к проблеме «голых данных» . Мы хотим держать это в секрете, и это хорошее желание.

Теперь мы хотим иметь возможность печатать температуру в градусах Фаренгейта. Наиболее очевидный подход заключается в том, чтобы ввести другой метод toFahrenheitString() или добавить логический флаг к объекту, который изменит поведение метода toString() , верно? Любое из этих решений лучше, чем добавление метода getT() , но ни одно из них не является идеальным.

Что если мы создадим этот декоратор:

1
2
3
4
5
6
7
8
class TempFahrenheit implements Temperature {
  private TempCelsius origin;
  public String toString() {
    return String.format(
      "%d F", this.origin.t * 1.8 + 32
    );
  }
}

Это должно работать просто замечательно:

1
2
3
Temperature t = new TempFahrenheit(
  new TempCelsius(35)
);

Единственная проблема заключается в том, что он не будет компилироваться в Java, поскольку класс TempFahrenheit не имеет доступа к частному t в классе TempCelsius . И если мы сделаем это общедоступным, каждый сможет прочитать его напрямую, и у нас возникнет проблема «голых данных» — серьезное нарушение инкапсуляции.

Однако, если мы разрешим этот доступ только одному классу, все будет хорошо. Примерно так (не будет работать в Java; это просто концепция):

1
2
3
4
5
6
7
class TempCelsius {
  trust TempFahrenheit; // here!
  private int t;
  public String toString() {
    return String.format("%d C", this.t);
  }
}

Поскольку это ключевое слово trust помещено в класс, который разрешает доступ, у нас не будет проблемы «голых данных» — мы всегда будем точно знать, какие объекты обладают знаниями о t . Когда мы что-то меняем в t , мы точно знаем, где обновить код.

Что вы думаете?

Вы можете также найти эти связанные сообщения интересными: инкапсуляция покрывает голые данные ; Сколько инкапсулируют ваши объекты? ; Поведение объекта не должно быть настраиваемым ; Как неизменный объект может иметь состояние и поведение? ; Градиенты неизменности ;

JavaScript отключен в вашем браузере, поэтому вы не можете видеть комментарии под этим сообщением.

Ссылка: Могут ли объекты быть друзьями? от нашего партнера JCG Егора Бугаенко в блоге « О программировании» .