wake-up-neo.net

Java: statisches Feld in abstrakter Klasse

Ich fange einfach mit einem Beispiel an, das es am besten erklärt:

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

Dies wird ausgedruckt:

b.str = abc

c.str = abc

Ich möchte jedoch eine Lösung, bei der jede Unterklasse, die die Superklasse instanziiert, ihre own - Klassenvariable hat. Gleichzeitig möchte ich diese Klassenvariable über den Bezeichner oder einen Methodenaufruf referenzieren, der in definiert ist die abstrakte Superklasse.

Ich möchte also, dass die Ausgabe lautet: 

b.str = 123 

c.str = abc

Ist das machbar? 

42
Tommy

Wenn Sie möchten, dass die Klassen B und C separate statische Variablen haben, müssen Sie die Variablen in diesen Klassen deklarieren. Grundsätzlich passen statische Elemente und Polymorphismus nicht zusammen.

Beachten Sie, dass der Zugriff auf statische Member über Verweise eine wirklich schlechte Idee ist, was die Lesbarkeit angeht - dies macht look so, als hinge es vom Wert des Verweises ab, wenn dies nicht wirklich der Fall ist. Ihr aktueller Code wird also nicht kompiliert, wenn Sie str nach B und C verschoben haben. Stattdessen benötigen Sie dies

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

Wenn Sie wirklich auf den Wert polymorph zugreifen müssen (d. H. Über eine Instanz von A), besteht die Möglichkeit, einen polymorphen Getter zu erstellen:

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

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

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

(und dasselbe für C).

Auf diese Weise erhalten Sie das gewünschte Verhalten in Bezug auf das Fehlen eines separaten Variable pro Instanz. Sie können es jedoch weiterhin polymorph verwenden. Es ist ein wenig seltsam für ein Instanzmitglied, einen statischen Wert wie diesen zurückzugeben, aber Sie verwenden den Wert für Polymorphismus des Typs.

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

Dann kannst du haben

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

Der Setter und der Getter sind meine Ergänzung. Sie können die Variable einfach nicht statisch machen.

Update Wenn Sie die statische-pro-Unterklasse haben möchten, können Sie Folgendes haben:

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

und dann:

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

Dies ist jedoch im Allgemeinen eine schlechte Idee.

6
Bozho

Fügen Sie die statische Variable in jede Unterklasse ein und fügen Sie der abstrakten Superklasse eine (nicht statische) abstrakte Methode hinzu:

abstract String getStr();

Implementieren Sie anschließend die getStr () - Methode in jeder Unterklasse, indem Sie das statische Feld dieser speziellen Unterklasse zurückgeben.

public class B extends A {
 private static String str;

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

Da Sie den Wert oder str in Unterklassen trotzdem hartcodieren, können Sie Folgendes tun:

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";
   }
}

Dies würde in Ihrem Fall den Trick tun.

Dann sollten Sie es natürlich mit der folgenden Methode aufrufen:

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

im System ist nur eine Instanz der statischen Variablen vorhanden.

die statische Variable wird beim Start in das System geladen, bevor die Klasse geladen wird.

grund für beide Ausdrucke von abc ist, dass Sie im letzten Wert den Wert von str als abc festlegen.

2
Chirag Tayal

Dadurch wird die gewünschte Ausgabe gedruckt:

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

Es ist das, was ich vermieden habe, um in jeder Unterklasse dieselbe Methode implementieren zu müssen. Es basiert auf der Antwort von Bozho. Vielleicht kann es jemandem helfen.

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

Ich denke, eine Möglichkeit, dies zu erreichen, besteht darin, ein Singleton für die Klasse B und C zu verwenden, um statische Methoden und Felder nachzuahmen. Beide können die abstrakte Klasse A erweitern, haben jedoch ihre eigenen Werte von str ..

0
Martin Konecny