Javaで可変ノードと不変ノードを作成したいのですが、可変以外はすべて同じでなければなりません。基本クラスと、可変クラスと不変クラスの 2 つの派生クラスを実装する方法は?
5 に答える
可変クラスと不変クラスの違いは、不変クラスには、内部状態を変更するセッターやその他のメソッドがないことです。状態はコンストラクターでのみ設定できます。
サブクラスがある場合、これはもはや当てはまらないため、親クラスをImmutableと呼ぶのは悪い考えです。名前は誤解を招く可能性があります:
ImmutableNode node = new MutableNode();
((MutableNode)node).change();
あなたがする必要があるのは、保護された変数を持つ単一の基本クラスを作成することだけです
public class Base{
protected int foo;
}
変更可能なものは、変数を設定できる必要があります
public class MutableBase extends Base{
public void setFoo(){}
}
不変のものは、変数を一度だけ設定できる必要があります
public class ImmutableBase extends Base{
public ImmutableBase(int foo){
this.foo = foo;
}
}
ほとんどの不変クラスには、インスタンスを変更せずに内部の変数に作用するメソッドがあります。文字列はこれを行います。このようなものが必要になる場合があります
public ImmutableBase add(int bar){
return new ImmutableBase(this.foo+bar);
}
これの優れた点は、クラスのユーザーが各インスタンスの内部をあまり制御/心配する必要がないことです。これにより、Java ではすべてがオブジェクト参照によって渡されるため、操作が簡単になります。そのため、String または ImmutableBase を渡す場合、変更されることを心配する必要はありません。
もう1つのオプションは、 UnmodizableListと同じ戦略を使用することです。まず、タイプを指定するインターフェースを作成します。
interface List<T>{
List<T> add(T t);
T getAt(int i);
...
}
次に、すべてのビジネスロジックを使用して可変クラスを実装します。
public class MutableList<T> implements List<T>{
@Override
List<T> add(T t){ ... }
@Override
T getAt(int i){ ... }
...
}
そして最後に、不変クラスを作成して、可変クラスのビューにします。同じインターフェイスを実装しますが、すべての読み取りメソッド呼び出しを表示されたオブジェクトに委任し、例外を使用して書き込みアクセスを禁止します。
public class UnmodifiableList<T> implements List<T>{
//This guy will do all hard work
private List delegate;
public UnmodifiableList(List<? extends T> delegate){
this.delegate = delegate;
}
//Forbidden mutable operation: throw exception!
@Override
List<T> add(T t){
throw new UnsupportedOperationException("List is unmodifiable!");
}
//Allowed read operation: delegate
@Override
T getAt(int i){
return delegate.getAt(i);
}
...
}
このアプローチには、ビジネスロジックを一度だけ実装するという利点があり、オブジェクトを不変のオブジェクトに変換する前に、独自のメソッドと検証チェックを使用して最初にオブジェクトを構築できます。
クラスが不変であるためには、finalとして宣言する必要があり、setterメソッドを持たないようにする必要があります。最終宣言は、それを拡張できず、追加の可変プロパティが追加されないことを保証します。
class Base {
protected int var1;
protected int var2;
public getVar1() {return var1;}
public getVar2() {return var2;}
}
class Mutable extends Base {
public setVar1(int var1) {this.var1 = var1}
public setVar2(int var2) {this.var2 = var2}
}
final class Immutable extends Base { //final to avoid being extended and then implement the setters
}
それは私ができる小さなことですか?しかし、なぜそのようなシナリオが必要になるのでしょうか。
不変クラスとは、一度作成すると内容を変更できないクラスです。不変オブジェクトは、状態を変更できないオブジェクトです。
Java の不変クラスの一般的な例はStringクラスです。