Класс Tutor
представляет множество аспектов, способствующих его неизменности:
- класс окончательный
-
Set<Student>
защищен от изменений
- нет метода, позволяющего напрямую изменять состояние класса
Однако защитная копия конструктора не завершена.
Также необходимо скопировать элементы Student
s переданного массива. В противном случае клиент конструктора может изменить любой их экземпляр и сделать изменяемый экземпляр Tutor
, например:
Student[] students = ...;
Tutor tutor = new Tutor(name, students);
students[0].setName("new Name!"); // break the immutability of Tutor
Вы должны написать что-то вроде:
public Tutor(String name, Student[] students){
this.name = name;
tutees = new HashSet<Student>();
for (Student student : students){
Student copy = new Student(student.getName(),
student.getCourse());
tutees.add(copy);
}
}
Кроме того, обратите внимание, что Set
, возвращаемое getTutees()
, не модифицируется, но элементы, содержащиеся в нем как Student
, являются изменяемыми.
Таким образом, чтобы сделать Tutor неизменным, вы также должны создать копию элементов Student при возврате getTutees()
, например:
public Set<Student> getTutees(){
Set<Student> students = new HashSet<>();
for (Student student : tutees){
Student copy = new Student(student.getName(),
student.getCourse());
students.add(copy);
}
return Collections.unmodifiableSet(students);
}
Как вы можете заметить, для получения неизменяемости в этих условиях (экземпляр, который мы хотим неизменным, но который содержит коллекцию, ссылающуюся на изменяемые экземпляры), требует написания большего количества кода (для чтения / обслуживания / тестирования) и выполнения большей обработки (так медленно, чтобы выполнить).
Если бы Student
был неизменным классом, оригинального getTutees()
и исходного конструктора было бы достаточно.