2012-11-03 5 views
6

나는 클래스 라이브러리를 개발 중이다.불변 클래스를위한 clone() 구현

  1. 몇 가지 기본 방법에 대한 구현을 제공하는 행렬에 대한 추상 기본 클래스 Matrix가 있습니다.
  2. Matrix에서 파생 된 것은 다양한 유형의 행렬에 대한 구체적인 하위 클래스입니다.
  3. 매트릭스가 복제 가능해야한다는 요구 사항이 있으므로 Matrix는 Cloneable 인터페이스를 구현합니다.
  4. 는 매트릭스로부터 유도 된 클래스 중 일부

이 대신에 오브젝트의 복제를 반환 객체 자체가 반환 불변 클래스 '복제 방법 허용 될 불변?

설명에 대한 몇 가지 (간략화 됨) 코드 : 나는 충분하다 super.clone()를 호출 생각했을 것이다

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; 
    } 
    ... 
} 
+0

왜 처음부터 개체를 복제 할 수 있습니까? –

+1

원래 행렬 주위에 작은 래퍼를 반환하고 즉시 값을 계산하면 일부 작업 (예 : 전치)을 쉽게 구현할 수 있습니다. 또한 일부 상황 (예 : 거대한 행렬의 연산)에서 메모리 풋 프린트를 줄일 수 있습니다. 원래의 행렬이 변경되지 않는 한 이것은 잘 작동합니다. 그렇지 않으면 원본 행렬을 변경하면 결과에 부작용이 발생합니다. 하지만 이제 불변의 서브 클래스에 대해서만 객체 자체를 리턴하는 getImmutable() 메소드를 제공함으로써이를 해결했습니다. 반면 변경 가능한 서브 클래스는 불변의 사본을 리턴합니다. 더 이상 복제 할 필요가 없습니다. – Axel

답변

8

.

클래스가 변경 불가능한 경우, 변경시에 변경 가능한 클래스가 이미 복제 된 상태 여야합니다. 그러므로 나는 여러분의 클래스가 가지고있는 필드의 얕은 복사본을 갖는 것이 안전하다고 생각할 것입니다.

JavaDocs의 상태는 x.clone() != x입니다. 이것이 절대적인 요구 사항은 아니지만, 귀하의 계획에 의해 정확히 반납되는 것은 단지 this입니다.

-1

예 String (불변의 클래스)의 동작을 보면, 내용이 같으면 같은 객체가 돌려 주어집니다. 따라서 여러분의 말이 맞습니다. clone() 메서드는이 값만 반환해야합니다.

+1

그러나 문자열은 복제 할 수 없습니다. – Axel

+0

예 문자열은 복제 할 수 없지만 두 객체의 내용이 같고 다른 객체를 만드는 대신 동일한 객체를 반환해야하는 불변 인 경우 메모리를 절약합니다. – zaffargachal

+1

그게 제가 생각한 것입니다. 마침내 나는 다른 무언가에 의지했다. Matrix가 Cloneable을 구현해야한다는 요구 사항은 일부 메소드가 인수로 전달 된 행렬의 불변 사본을 작성해야했기 때문입니다. 그래서 나는 그 방법들 안에 매트릭스 논증을 복제했습니다. 이제, 추상적 인'getImmutable()'메소드를 매트릭스 클래스에 추가하고 대신 그것을 사용합니다. 이렇게하면 불변 클래스에 대한 불필요한 복제본을 만들지 않아도되지만, 변경 가능한 클래스는 불변의 복사본을 만들어이 메서드를 구현할 수 있습니다. – Axel

4

불변 클래스의 clone() 구현에서 this을 그냥 반환하십시오.

2

당신이 불변 클래스를 가질 수 있지만 단순히 정말 또는 변경 가능하지 않을 수도 있습니다 것들에 clone을 사용하여 훨씬 값이 표시되지 않는, 자신에 대한 참조를 반환하는 clone을 구현, 불변의 가변 대처를 만드는 몇 가지 방법을 결석 그 반대도 마찬가지입니다.

나는 AsImmutable, AsMutableAsNewMutable 방법과 함께 방법 IsImmutableIsWritable을 포함하도록 Matrix 클래스 기지에 대한 더 좋을 거라 봅니다; 행렬을 읽고 쓰는 메소드도 포함해야한다. (쓰기가 불가능한 행렬에 "write"메소드를 호출하면 예외가 발생한다.)

적절한 데이터를 미리 초기화 새로운 불변 ​​또는 가변 행렬을 생성한다하는 Matrix 주어진 정적 메소드 CreateImmutableMatrixCreateMutableMatrix과, 정의.

변경 가능한 클래스는 자신을 돌아, CreateImmutableMatrixAsMutable을 자신을 전달하는 AsImmutable를 구현해야하고, AsNewMutableCreateMutableMatrix에 자신을 전달합니다.

불변의 클래스는 AsImmutableAsNewMutable 전화, AsMutable을 자신을 반환하기 위해 구현해야하고, AsNewMutableCreateMutableMatrix 자신을 전달합니다.

읽기 전용 래퍼은, 랩 된 객체에 AsNewMutable를 호출하는 랩 객체에 AsImmutableAsMutableAsNewMutable를 호출하는 AsImmutable를 구현해야합니다.

복사 또는 변형 할 필요가있을 수도 있고 그렇지 않을 수도있는 매트릭스를 수신하는 객체는 단순히 필드 (예 : Foo)에 저장할 수 있습니다. 행렬을 변경해야하는 경우 FooFoo.AsMutable()으로 바꿀 수 있습니다. 행렬을 포함하는 객체를 복사해야하는 경우 사본의 필드를 변경해야하는지에 따라 필드가 사본에서 Foo.AsImmutable() 또는 Foo.AsNewMutable()으로 대체되어야합니다.

+0

답장을 보내 주셔서 감사합니다. 꽤 잘 그 동안 구현 한 솔루션을 설명합니다. – Axel

+0

@supercat 상위 뷰 인터페이스가있는 변경 가능/변경 가능 클래스에 대한 유사한 체계를 구현 중입니다 (또한이 게시물을 보았습니다 : http://programmers.stackexchange.com/questions/221762/why-doesnt-java-8-include- 불변 - 콜렉션). 나는 AsNewMutable과 AsImmutable 메소드의 목적을 본다. 그러나 나는 AsMutable에 대해서 확신하지 못한다. 변경 가능한 객체에서 그런 메소드를 호출하지 않는다면 어쨌든 그 객체를 가변적 인 버전으로 전달해야했음을 나타낸다. ? 객체에서이 메서드를 호출하면 부작용이 있거나 그렇지 않을 수도 있음을 의미합니다. –

+1

@AlexanderKaratarakis : 아이디어는 (1) 불변이거나 (2) 문제가되는 변경 가능한 객체에 대해 우주에서 유일한 참조를 유지할 수있는 참조에 대해 'AsMutable'을 호출하는 것입니다. 이는 불변 객체에 대해 "AsMutable"을 호출하여 생성되었으며 그 이후로는 공유되지 않았습니다.유니버셜에서 변경 가능한 객체에 대한 참조 만 수행하면'AsNewMutable'을 호출 할 수는 있지만 불필요하게 느려질 수 있습니다. 코드가 예를 들어 객체를 복제하는 경우 10 개의 "값 비싼"속성을 가질 수 있으며, 단지 하나 또는 두 개만 변경해야 할 가능성이 있습니다. – supercat

0

클래스가 final이 아니므로 엄격하게 변경할 수 없습니다. 변경할 수있는 하위 클래스가있을 수 있습니다. 누군가가 ImmutableMatrix를 서브 클래 싱하기를 원한다면 당신은 그냥 this을 반환하는 경우

, 그는 super.clone()를 호출하여 clone()을 구현 할 수 없습니다. 따라서이 경우 super.clone()으로 전화해야합니다.

그러나 최종적으로 클래스를 만들면 this을 반환하지 않는 이유가 표시되지 않습니다.

+0

클래스에 대한 계약에 따라 관찰 된 상태가 변경되지 않는다고 밝혀지면이를 위반하는 모든 하위 클래스가 손상됩니다. 상속 가능한 클래스가 하위 클래스가 계약을 준수한다는 것을 보증하는 것이 거의 불가능할지라도, 일반적인 방법은 파생 클래스가 그렇게하는 보안과 관련이없는 상황을 가정하는 것입니다. 그것은 일반적인 관행이 아니 었습니다. 상속은 거의 쓸모가 없었을 것입니다. 불변성을 다른 계약상의 약속과 근본적으로 다른 것으로 간주 할 이유는 없습니다. – supercat

+0

@supercat 하위 클래스가 불변 인 경우에도 super.clone()을 호출하여 복제를 구현할 수 있습니다. – WilQu

+0

하위 클래스가 불변 인 경우 기본 클래스의 모든 파생 클래스가 아닌 경우에도 단순히 '반환'을 수행하여 '복제'를 구현할 수 있습니다 이것; 클래스가 * 계약에 의해 불변으로 * 지정 되었다면, 클래스를 상속받을 수있는 경우에도'clone'을'return this '로 구현하는 것이 허용 될 수 있습니다. 단, 파생 된 클래스가 복제본을 합법적으로 수행하지 않을 수있는 계약 구별되는 것. – supercat

관련 문제