Реализация clone () для неизменяемых классов
Я разрабатываю библиотеку классов.
- у меня есть абстрактная Матрица базового класса для матриц, которая предоставляет реализации для некоторых основных методов.
- производные от матрицы являются конкретными подклассами для различных типов матриц.
- у меня есть требование, чтобы матрицы были клонируемыми, поэтому Матрица реализует клонируемый интерфейс.
- некоторые классы, производные от Matrix, неизменяемы
это допустимо ли для методов клонирования неизменяемых классов, что вместо возврата клона объекта возвращается сам объект?
некоторый (упрощенный) код для уточнения:
abstract class Matrix implements Cloneable {
...
}
class ImmutableMatrix extends Matrix {
ImmutableMatrix clone() {
return this;
}
...
}
class SomeOtherMatrix extends Matrix {
SomeOtherMatrix clone() {
SomeOtherMatrix other = super.clone();
...
return other;
}
...
}
5 ответов
Я бы подумал, что звонит super.clone()
будет достаточно.
Если ваш класс неизменяем, то он должен был уже клонировать любые изменяемые классы, когда он был построен. Поэтому я думаю, что было бы безопасно иметь неглубокие копии любых полей вашего класса.
JavaDocs утверждают, что x.clone() != x
предпочтительнее. Хотя это не является абсолютным требованием, это, безусловно, будет нарушено вашим планом просто вернуться this
.
в то время как вы могли бы иметь неизменяемые классы просто реализовать clone
чтобы вернуть ссылки на себя, я действительно не вижу большой ценности в использовании clone
на вещи, которые могут быть или не могут быть изменяемыми, отсутствует какой-либо способ сделать изменяемые справляется с неизменяемыми вещами и наоборот.
я бы подумал, что это было бы лучше для вашей базы Matrix
класс для включения методов IsImmutable
и IsWritable
вместе с AsImmutable
, AsMutable
и AsNewMutable
методы; он также должен включать методы для чтения и напишите матрицу (хотя вызов метода "write" на незаписываемой матрице должен вызвать исключение).
определить статические методы CreateImmutableMatrix
и CreateMutableMatrix
, которая, учитывая Matrix
, создаст новую неизменяемую или изменяемую матрицу, которая предварительно инициализируется соответствующими данными.
изменяемые классы должны реализовать AsImmutable
перейти к CreateImmutableMatrix
, AsMutable
вернуться самим, и AsNewMutable
перейти к CreateMutableMatrix
.
неизменяемые классы следует реализовать AsImmutable
чтобы вернуть себе AsMutable
называть AsNewMutable
и AsNewMutable
перейти к CreateMutableMatrix
.
читать-только фантики реализации AsImmutable
называть AsImmutable
на завернутые объекты, и AsMutable
и AsNewMutable
называть AsNewMutable
на завернутые объекты.
объект, который получает матрицу, которую ему может потребоваться или не нужно копировать или мутировать, может просто хранить ее в поле (например,Foo
). Если ему нужно мутировать матрицу, он может заменить Foo
С Foo.AsMutable()
. Если объект, содержащий матрицу, необходимо скопировать, поле следует заменить в копии либо Foo.AsImmutable()
или Foo.AsNewMutable()
в зависимости от того, будет ли поле в копии, вероятно, необходимо мутировать.
ваш класс не является строго неизменяемым, поскольку он не является окончательным: могут быть изменяемые подклассы.
если кто-то хочет подкласс ImmutableMatrix
, Он не сможет реализовать clone()
по телефону super.clone()
Если вы просто вернуть this
. Поэтому в этом случае вы должны позвонить super.clone()
.
однако, если вы сделаете свой класс окончательным, я не вижу причин, почему бы просто не вернуться this
.
да если мы видим поведение строки (неизменяемый класс), если содержимое одинаковое , возвращается тот же объект, поэтому я считаю, что вы правы, метод clone () должен возвращать только это.