2011-02-04 12 views
40

の静的フィールド、最高のそれを説明する:の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

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

だから私は出力がなりたい:= 123

c.str

b.str = ABC

はなんとかということですか?

答えて

3

各サブクラスに静的varibaleを入れて、抽象スーパークラスに(静的でない)抽象メソッドを追加します。

abstract String getStr(); 

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

public class B extends A { 
private static String str; 

    @Override 
    public String getStr() { 
    return B.str; 
    } 
} 
+0

私の投稿を編集しましたが、エラーです。つまり、それぞれのオブジェクトは、同じサブクラスのすべてのオブジェクト間で共有される値への参照を持つ必要がありますが、必ずしも異なるサブクラスのオブジェクト間で共有される必要はありません。 – Tommy

+0

私の答えも更新 – Ralph

+0

もちろん。ありがとうございました。 – Tommy

6
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); 
} 

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

+0

これはgetterとsetterがなくても動作します。次に、str変数がpublicであることを確認してください。これはお勧めできません。 –

+0

@Thijs:静的なフィールドに直接アクセスする方法(特にここでは 'getStr()'のような読み込み専用メソッド)が好きです。 –

+0

ありがとう!なぜあなたはそれが悪い考えだと思っているのか分かりません。このソリューションでは、サブクラスで何もコード化する必要はなく、すべてがスーパークラスで実装されています。もちろん、クラス変数を設定するオブジェクトのメソッドを呼び出す(または、あなたの解決策がそうであるように見せかける)ことは奇妙に見えます。しかし、とにかくそれを逃れる方法はないようです(ジョン・スケートとラルフの解答)。 – Tommy

2

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

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

理由は、abcが最後にabcとしてstrの値を設定したためです。

2

これは、あなたが望む出力に印刷されます:あなたは、クラスBとCは別の静的変数を持っているしたい場合は、これらのクラス内の変数を宣言する必要があります

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

ありがとう。ほとんどそこに:)ラルフの答えを見てください。非常にうまく説明できないかもしれません。 – Tommy

45

を。基本的に、静的メンバーと多型は合わない。参照を介して静的メンバにアクセスすること

注読みやすさの面で本当に悪い考えである - それはそれは本当にないとき、それは、参照の値に依存のように、それはを見てます。あなたはBとCまでstrを移動したときに、あなたの現在のコードも、あなたが本当にAのインスタンスを通じて、すなわち(ポリモーフィック値にアクセスする必要がある場合はその代わりに、あなたは

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

をする必要がありますコンパイルされません)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と同じです)。

このようにして、インスタンスごとに別々の変数を持たないという点で必要な振舞いを得ることができますが、それでもポリモーフィックに使用できます。インスタンスメンバーがこのような静的な値を返すのはちょっと奇妙ですが、基本的に型の多態性の値を使用しています...

+4

私の経験では、Eclipseをコンパイルエラーとしてマークする価値があります。 – biziclop

+7

@biziclop:私も。だから私はEclipseの最初の場所でそれをリクエストしています:https://bugs.eclipse.org/bugs/show_bug.cgi?id=21109 :) –

+0

それを知っておいてください。 :) – biziclop

2

サブクラスで値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()); 
    } 
} 
0

私はこれにアプローチする一つの方法は、静的メソッドやフィールドを模倣するために、クラスBCためにシングルトンを使用することだと思います。どちらも抽象クラスAを拡張しますが、strの独自の値を持ちます。

1

これは、すべてのサブクラスで同じメソッドを実装しなければならないことを避けたものです。それは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"); 
    } 
} 
関連する問題