Неизменяемый интерфейс (Uyn[byuxybdw numyjsywv)
В объектно-ориентированном программировании, «неизменяемый Интерфейс» — это шаблон для проектирования неизменяемого объекта.[1][2][3] Неизменяемый интерфейс включает в себя определение типа, который не предоставляет никаких методов, которые могут изменить состояние. Объекты, на которые ссылается этот тип, выглядят как неизменяемые.
Пример
[править | править код]Java
[править | править код]Рассмотрим класс java, который представляет собой двухмерную точку.
public class Point2D {
private int x;
private int y;
public Point2D(int x, int y) { this.x = x; this.y = y; }
public int getX() { return this.x; }
public int getY() { return this.y; }
public void setX(int newX) { this.x = newX; }
public void setY(int newY) { this.y = newY; }
}
Класс Point2D является изменяемым: его состояние может быть изменено после создания, если вызвать один из методов-сеттеров (setX()
или setY()
).
Неизменяемый интерфейс для Point2D может быть определен как:
public interface ImmutablePoint2D {
public int getX();
public int getY();
}
Сделав Point2D реализующим ImmutablePoint2D, код клиента теперь может использовать тип, который не имеет изменяющих методов, и, таким образом, остается неизменяемым. Это демонстрируется в следующем примере:
ImmutablePoint2D point = new Point2D(0,0); // на конкретный экземпляр Point2D ссылается неизменяемый интерфейс
int х = point.getX(); // допустимый вызов метода
point.setX(42); // ошибка компиляции: метод setX() не существует в типе ImmutablePoint2D
Имея только неизменяемый интерфейс, невозможно вызвать метод, который изменяет состояние конкретного объекта.
Преимущества
[править | править код]- Четко передает намерения о неизменяемости типа.
- В отличие от типов, реализующих шаблон неизменяемая обертка, не нужно нейтрализовать изменяющие методы, путем использования инструкции «нет эксплуатации», или бросать исключение во время выполнения, когда изменяющий метод вызывается.
Недостатки
[править | править код]- Возможно для экземпляров, на которые ссылается неизменяемый интерфейс, привести тип к конкретному изменяемому типу, и уже тогда изменить состояние. Например:
public void mutate(ImmutablePoint2D point) {
((Point2D)point).setX(42); // допустимый вызов, поскольку
// аргумент point был приведен к типу Point2D
}
- Конкретные классы должны явно объявлять в их реализации неизменяемый интерфейс. Это не может быть возможно, если конкретный класс «принадлежит» стороннему коду, например, если оно содержится в библиотеке.
- Объект не является на самом деле неизменяемым и, следовательно, не подходит для использования в структурах данных, требующих неизменяемость, таких как хеш-map-ы. И объект может быть изменен одновременно на «изменяемой стороне».
- Некоторые оптимизации компилятора, доступные для неизменяемых объектов, могут быть недоступны для изменяемых объектов.
Альтернативы
[править | править код]Альтернативой неизменяемому интерфейсу является шаблон неизменяемая обёртка.
Ссылки
[править | править код]- ↑ Immutable Interface . Дата обращения: 10 мая 2016. Архивировано 27 сентября 2010 года.
- ↑ immutable : Java Glossary . Дата обращения: 10 мая 2016. Архивировано 10 апреля 2016 года.
- ↑ Practical Java Praxis 65: Use Inheritance or Delegation to Define Immutable Classes | Practical Java Praxis 65: Use Inheritance or Delegation to Define Immutable Classes | Inf… Дата обращения: 10 мая 2016. Архивировано 3 июня 2016 года.