web-dev-qa-db-de.com

Abstrakte Variablen in Java?

Ich komme aus c #, wo das einfach und möglich war.

Ich habe diesen Code:

public abstract class clsAbstractTable {

    public abstract String TAG;
    public abstract void init();

}

aber Eclipse sagt mir, dass ich illegalen Modifikator verwende. 

Ich habe diese Klasse:

public class clsContactGroups extends clsAbstractTable {


}

Ich möchte, dass die Variable und die Methode so definiert werden, dass Eclipse Prompt me, ich habe nicht-implementierte abstrakte variables und Methoden.

Wie muss ich meine abstrakte Klasse definieren, damit ich aufgefordert werden sollte, die Abstracts zu implementieren?

EDIT 1

Ich werde verschiedene Klassen für verschiedene DB-Tabellen erstellen. Jede Klasse sollte ihre eigene TABLENAME-Variable haben, keine Ausnahme. Ich muss sicherstellen, dass diese Variable jedes Mal statisch ist, wenn ich eine neue Klasse erstelle, die die abstrakte Klasse erweitert.

Dann habe ich in der abstrakten Klasse eine Methode zB: init ();

Wenn ich in dieser init () - Methode TABLENAME aufrufe, sollte es den Wert von der Unterklasse nehmen.

so etwas sollte auch klappen

String tablename=(clsAbstract)objItem.TABLENAME;
// where objItem can be any class that extended clsAbstract;

EDIT 2

Ich möchte, dass in jeder Klasse eine Konstante (statisch) definiert wird, deren Name abstrakt definiert ist. 

  • Ich definiere die Variable TABLENAME abstrakt, aber keinen Wert.
  • Ich erstelle eine clsContactGroups. Ich sollte aufgefordert werden, TABLENAME zu implementieren. Hier werden einige Daten abgerufen. zB: TABLENAME = "Kontaktgruppen";
  • Ich erstelle eine zweite Klasse clsContacts. Ich sollte aufgefordert werden, TABLENAME zu implementieren. Hier werden einige Daten abgerufen. zB: TABLENAME = "Kontakte";
    usw...
42
Pentium10

Ich denke, Ihre Verwirrung ist mit C # -Eigenschaften gegenüber Feldern/Variablen. In C # können Sie keine abstrakten Felder definieren, auch nicht in einer abstrakten Klasse. Sie können jedoch abstrakte Eigenschaften definieren, da dies effektiv Methoden sind (z. B. zu get_TAG() und set_TAG(...) kompiliert).

Einige haben daran erinnert, dass Sie niemals öffentliche Felder/Variablen in Ihren Klassen haben sollten, auch nicht in C #. Mehrere Antworten haben angedeutet, was ich empfehlen würde, aber nicht klar gemacht. Sie sollten Ihre Idee mit getTAG () als JavaBean-Eigenschaft in Java übersetzen. Dann müssen Ihre Unterklassen dies implementieren (ich habe auch ein Projekt mit Tabellenklassen geschrieben, die dies tun).

So können Sie eine abstrakte Klasse wie folgt definieren ...

public abstract class AbstractTable {

    public abstract String getTag();
    public abstract void init();

    ...
}

In allen konkreten Unterklassen müssten Sie dann eine statische Endvariable (Konstante) definieren und diese aus der getTag() zurückgeben, z.

public class SalesTable extends AbstractTable {

    private static final String TABLE_NAME = "Sales";

    public String getTag() {
        return TABLE_NAME;
    }

    public void init() {
        ...
        String tableName = getTag();
        ...
    }

}

EDIT:

Sie können geerbte Felder (in C # oder Java) nicht überschreiben. Sie können auch keine statischen Member überschreiben, egal ob es sich um Felder oder Methoden handelt. Dies ist also auch die beste Lösung dafür. Ich habe mein Beispiel für die init-Methode oben geändert, um zu zeigen, wie dies verwendet wird - denken Sie wiederum an die getXXX-Methode als Eigenschaft.

47
Kevin Brock

Definieren Sie in der abstrakten Klasse einen Konstruktor, der das Feld so festlegt, dass die konkreten Implementierungen der Spezifikation entsprechen, die zum Aufrufen/Überschreiben des Konstruktors erforderlich ist.

Z.B.

public abstract class AbstractTable {
    protected String name;

    public AbstractTable(String name) {
        this.name = name;
    }
}

Wenn Sie AbstractTable erweitern, wird die Klasse erst kompiliert, wenn Sie einen Konstruktor hinzufügen, der super("somename") aufruft.

public class ConcreteTable extends AbstractTable {
    private static final String NAME = "concreteTable";

    public ConcreteTable() {
        super(NAME);
    }
}

Auf diese Weise müssen die Implementierer name einstellen. Auf diese Weise können Sie auch den Konstruktor der abstrakten Klasse überprüfen (null), um ihn robuster zu machen. Z.B:

public AbstractTable(String name) {
    if (name == null) throw new NullPointerException("Name may not be null");
    this.name = name;
}
58
BalusC

Keine abstrakten Variablen in Java (oder C++).

Wenn die übergeordnete Klasse eine Variable hat und eine untergeordnete Klasse das übergeordnete Element erweitert, muss das untergeordnete Element die Variable nicht implementieren. Es braucht nur Zugriff auf die Instanz der übergeordneten Instanz. Entweder get/set oder geschützter Zugang reicht aus.

"... also sollte ich aufgefordert werden, die Abstracts zu implementieren"? Wenn Sie eine abstrakte Klasse erweitern und keine abstrakte Methode implementieren, werden Sie vom Compiler aufgefordert, diese entweder zu implementieren oder die Unterklasse als abstrakt zu markieren. Das ist die Aufforderung, die Sie bekommen.

6
duffymo

Fügen Sie diese Methode einfach zur Basisklasse hinzu

public abstract class clsAbstractTable {

    public abstract String getTAG();
    public abstract void init();

}

Jetzt sollte jede Klasse, die die Basisklasse erweitert (und nicht abstrakt sein möchte), eine TAG bereitstellen

Sie können sich auch für die Antwort von BalusC entscheiden

2
Lombo

Das Beste, was Sie tun können, ist ein Zugriff/Mutator für die Variable.
Etwas wie getTAG ()
Auf diese Weise müssten alle implementierenden Klassen sie implementieren.

Abstrakte Klassen werden verwendet, um abstraktes Verhalten und nicht Daten zu definieren.

2
Padmarag

Warum möchten Sie, dass alle Unterklassen die Variable definieren? Wenn jede Unterklasse es haben soll, definieren Sie es einfach in der Oberklasse. Übrigens, in Anbetracht der Tatsache, dass es gut ist OOP zu üben, Felder sowieso nicht freizulegen, ist Ihre Frage noch weniger sinnvoll.

1

Ändern Sie den Code in:

public abstract class clsAbstractTable {
  protected String TAG;
  public abstract void init();
}

public class clsContactGroups extends clsAbstractTable {
  public String doSomething() {
    return TAG + "<something else>";
  }
}

Auf diese Weise haben alle Klassen, die diese Klasse erben, diese Variable. Sie können 200 Unterklassen erstellen und dennoch wird jede dieser Variablen diese Variable haben.

Randbemerkung: Verwenden Sie kein CAPS als Variablennamen. Es ist allgemein bekannt, dass sich alle Begrenzungskennungen auf Konstanten beziehen, d. h.

1
dimitarvp

Wenn Sie Metadaten pro Klasse hinzufügen möchten, ist möglicherweise eine Anmerkung der richtige Weg.

Sie können jedoch nicht das Vorhandensein einer Anmerkung in der Schnittstelle erzwingen, ebenso wie Sie keine statischen Member oder das Vorhandensein eines bestimmten Konstruktors erzwingen können.

1
Joachim Sauer

Da es keine Implementierung einer Variablen gibt, kann sie nicht abstrakt sein;)

1
Tomas Vana

In meinem Experiment muss Java abstract class abstract keyword angeben. Umgekehrt wird der Fehler "abstract modifier kann hier nicht angegeben werden" angezeigt. Sie können abstract angeben Attribute wie gewöhnliche Attribute.

public abstract class Duck implements Quackable, Observable {
    // observerList should keep the list of observers watching this duck 
    List<Observer> observerList;

    public AttackBehavior attackBehavior;
    public FlyBehavior flyBehavior;

    public Duck() {
        observerList = new ArrayList<Observer>();
    }
}

Und in Unterklassen können Sie diese Attribute direkt verwenden this.flyBehavior oder this.attackBehavior. Sie müssen die Attribute im Attributfeld nicht neu schreiben.

0
Shark Deng

Verwenden Sie Aufzählungen, um Werte zu erzwingen, um gebundene Überprüfungen durchzuführen:

enum Speed {
    HIGH, LOW;
}
private abstract  class SuperClass {
    Speed speed;
    SuperClass(Speed speed) {
        this.speed = speed;
    }
}
private class ChildClass extends SuperClass {
    ChildClass(Speed speed) {
        super(speed);
    }
}
0
user531069