web-dev-qa-db-ja.com

Java:抽象クラスの静的フィールド

私はちょうどそれを最もよく説明する例から始めます:

public abstract class A{
    static String str;
}

public class B extends A{
    public B(){
        str = "123";
    }
}

public class C extends A{
    public C(){
        str = "abc";
    }
}

public class Main{

    public static void main(String[] args){
        A b = new B();
        A c = new C();
        System.out.println("b.str = " + b.str);
        System.out.println("c.str = " + c.str);
    }
}

これは印刷されます:

b.str = abc

c.str = abc

しかし、スーパークラスをインスタンス化する各サブクラスがownクラス変数を持ち、同時に識別子またはメソッド呼び出しを通じてそのクラス変数を参照できるようにしたい解決策が欲しい、抽象スーパークラスで定義されています。

したがって、出力を次のようにしたいと思います。

b.str = 123

c.str = abc

それはできますか?

47
Tommy

クラスBとCに別々の静的変数を持たせたい場合、それらのクラスで変数を宣言する必要があります。基本的に、静的メンバーとポリモーフィズムは共存しません。

参照を介して静的メンバーにアクセスすることは本当に読みやすさの点で悪い考えです-それはlookになります本当に。したがって、strをBおよびCに移動した場合、現在のコードはコンパイルされません。代わりに、

System.out.println("b.str = " + B.str);
System.out.println("c.str = " + C.str);

ポリモーフィックに(つまり、Aのインスタンスを介して)値にアクセスする必要がある場合、1つのオプションはポリモーフィックゲッターを作成することです。

public class A {
    public abstract String getStr();
}

public class B extends A {
    private static String str = "b";

    @Override public String getStr() {
        return str;
    }
}

(Cでも同じです)。

そうすれば、インスタンスごとに別個の変数を持たないという点で必要な動作が得られますが、多態的に使用することができます。インスタンスメンバーがこのような静的な値を返すのは少し奇妙ですが、基本的には、型の多態性の値を使用しています...

52
Jon Skeet
public abstract class A {
    private String str;
    public String getStr() { return str;}
    protected void setStr(String str) { this.str = str; }
}

その後、あなたが持つことができるでしょう

B b = new B();
b.getStr();

セッターとゲッターは私の追加であり、変数を非静的にするだけで行くことができます。

更新サブクラスごとに静的にしたい場合は、次のようにすることができます。

protected static Map<Class, String> values;
public abstract String getValue();

その後:

public String getValue() {
    values.get(getClass());
}
public void setValue(String value) {
    values.set(getClass(), value);
}

しかし、これは一般的に悪い考えです。

6
Bozho

各サブクラスに静的変数を配置し、(静的ではない)抽象メソッドを抽象スーパークラスに追加します。

abstract String getStr();

次に、この特別なサブクラスの静的フィールドを返すことにより、各サブクラスにgetStr()メソッドを実装します。

public class B extends A {
 private static String str;

  @Override
  public String getStr() {
    return B.str;
  }
}
3
Ralph

とにかくサブクラスで値またはstrをハードコーディングしているため、次のようなことができます。

public abstract class A{
    public abstract String getStr();
}

public class B extends A{
   public String getStr(){
      return "123";
   }
}

public class C extends A{
   public String getStr(){
      return "abc";
   }
}

これはあなたの場合にトリックを行います。

もちろん、次のようにメソッドで呼び出す必要があります。

public class Main{

    public static void main(String[] args){
        A b = new B();
        A c = new C();
        System.out.println("b.str = " + b.getStr());
        System.out.println("c.str = " + c.getStr());
    }
}
2
Goran Jovic

システムに存在する静的変数のインスタンスは1つだけです。

静的変数は、クラスがロードされる前の開始時にシステムにロードされます。

両方の時間abcが出力されるのは、最後にstrの値をabcに設定したためです。

2
Chirag Tayal

これにより、必要な出力が印刷されます。

public abstract class A{
}

public class B extends A{
    static String str;

    public B(){
        str = "123";
    }
}

public class C extends A{
    static String str;

    public C(){
        str = "abc";
    }
}

public class Main{

    public static void main(String[] args){
        A a = new B();
        A c = new C();
        System.out.println("B.str = " + B.str);
        System.out.println("C.str = " + C.str);
    }
}
2
Thijs Wouters

すべてのサブクラスで同じメソッドを実装しなければならないことを避けるためにしたことです。それはBozhoの答えに基づいています。たぶんそれは誰かを助けるかもしれません。

import Java.util.HashMap;
import Java.util.Map;

/**
 *
 * @author Uglylab
 */
public class SandBox {

    public static void main(String[] args) {
        A b = new B();
        A c = new C();
        System.out.println("b.str = " + B.getStr(b.getClass()));
        System.out.println("c.str = " + C.getStr(c.getClass()));
    }

}
 abstract class A{
    protected static Map<Class, String> values = new HashMap<>();


    public static String getStr(Class<? extends A> aClass) {
        return values.get(aClass);
    }

    public static void setStr(Class<? extends A> aClass, String s) {
        values.put(aClass, s);
    }

}

 class B extends A{
    public B(){
        setStr(this.getClass(),"123");
    }
}

 class C extends A{
    public C(){
        setStr(this.getClass(),"abc");
    }
}
1
Uglylab

これにアプローチする1つの方法は、クラスBおよびCにシングルトンを使用して静的メソッドとフィールドを模倣することだと思います。両方とも抽象クラスAを拡張できますが、str。の独自の値を持ちます。

0
Martin Konecny