以下のクラスがあるとします:
class Parent
{
private int ID;
private static int curID = 0;
Parent()
{
ID = curID;
curID++;
}
}
そしてこれら二つのサブクラス:
class Sub1 extends Parent
{
//...
}
そして
class Sub2 extends Parent
{
//...
}
私の問題は、これらの2つのサブクラスが、異なるクラスではなく、親クラスの同じ静的curIDメンバーを共有していることです。
だから私がこれをするなら:
{
Sub1 r1 = new Sub1(), r2 = new Sub1(), r3 = new Sub1();
Sub2 t1 = new Sub2(), t2 = new Sub2(), t3 = new Sub2();
}
R1、r2、r3のIDは0,1,2になり、t1、t2、t3のIDは3,4,5になります。これらの代わりに、t1、t2、t3の値を0、1、2にする必要があります。つまり、curID静的変数の別のコピーを使用します。
これは可能ですか?そしてどうやって?
他の人がすでに書いたように、静的メンバーはクラスにバインドされているため、クラスレベルでIDを追跡する必要があります。このような:
abstract class Parent {
private int ID;
Parent() {
ID = nextId();
}
abstract protected int nextId();
}
class Sub1 extends Parent {
private static int curID = 0;
protected int nextId() {
return curID++;
}
//...
}
class Sub2 extends Parent {
private static int curID = 0;
protected int nextId() {
return curID++;
}
//...
}
このアプローチはスレッドセーフではないことに注意してください。ただし、問題のコードはどちらでもありません。異なるスレッドから同時に同じサブクラスから新しいオブジェクトを作成してはなりません。
static
フィールド/メソッドは継承されますが、オブジェクト参照ではなく宣言するクラスに属しているため、オーバーライドできません。それらの1つをオーバーライドしようとすると、あなたはそれを隠すことになります。
可能ですが、単一のカウンタを使用することはできません。サブタイプごとにカウンターが必要です。たとえば、次のようなもの:
private static Map<Class<?>, Integer> counters = new HashMap<>();
Parent() {
Integer curID = counters.get(this.getClass());
if (curID == null) {
curID = 0;
}
ID = curID;
curID++;
counters.put(this.getClass(), curID);
}
注意:上記はスレッドセーフではありません。しかし、あなたの最初のコードはどちらでもありません...
他の答えが言ったこととは異なり、IS問題の解決策ですが、「静的継承」は含まれません。クラスごとのIDジェネレーターが必要です。
ここに良い例があります:
静力学は静力学であり、静力学である。 curID、periodのインスタンスは1つしかありません。したがって、Sub1とSub2に個別のカウンターが必要な場合は、これらの各クラスでstaticを宣言します。
静的要素はまったく継承されません。
実際にはSub1.curID
のようなものはありません。これはPersion.curID
を参照する正当な(まだ混乱を招く)方法です。
残念ながら、静的参照を使用して、目的を達成する方法はありません。それらは基本的に本質的には動作せず、動作することもできません。これらは静的に解決されるため、動的ディスパッチに依存できず、実行時のポリモーフィズムに依存できません。 JVM /コンパイラーが静的変数をこのように処理することを考えると、思い通りに実行できる回避策がないと確信しています。
IDを本当に静的にする必要がある場合は、各サブクラスで個別の静的変数を定義する必要があります。
static
メンバーは、JVMのPermGen
部分のParent.class
オブジェクトの一部です。そのクラスのすべてのインスタンス同じを共有静的変数。
すべてのサブクラスには独自のstatic curID
が必要です。