Реализация clone () для неизменяемых классов

Я разрабатываю библиотеку классов.

  1. у меня есть абстрактная Матрица базового класса для матриц, которая предоставляет реализации для некоторых основных методов.
  2. производные от матрицы являются конкретными подклассами для различных типов матриц.
  3. у меня есть требование, чтобы матрицы были клонируемыми, поэтому Матрица реализует клонируемый интерфейс.
  4. некоторые классы, производные от 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.


просто вернуть this в реализации clone () неизменяемых классов.


в то время как вы могли бы иметь неизменяемые классы просто реализовать 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 () должен возвращать только это.