Неизменяемый интерфейс
В объектно-ориентированном программировании, «неизменяемый Интерфейс» — это шаблон для проектирования неизменяемого объекта.[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 года.