web-dev-qa-db-ja.com

Javaの抽象変数?

私はこれが簡単で可能だったC#から来ています。

私はこのコードを持っています:

public abstract class clsAbstractTable {

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

}

しかし、Eclipseは違法な修飾子を使用していると教えてくれます。

私はこのクラスを持っています:

public class clsContactGroups extends clsAbstractTable {


}

Eclipseがプロンプトを表示、未実装の抽象変数およびメソッドを含むように定義された変数とメソッドが必要です。

抽象クラスを定義する必要があるので、抽象クラスを実装するように求められますか?

編集1

Dbテーブルごとに異なるクラスを作成します。各クラスには、独自のTABLENAME変数が必要です。例外はありません。抽象クラスを拡張する新しいクラスを作成するたびに、この変数が静的であることを確認する必要があります。

次に、抽象クラスにメソッドがあります。例:init();

このinit()メソッドでTABLENAMEを呼び出す場合、サブクラスから値を取得する必要があります。

このようなものもうまくいくはずです

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

編集2

抽象で定義された名前を持つ各クラスで定義された定数(静的)が必要です。

  • 変数TABLENAMEを抽象的に定義していますが、値が指定されていません。
  • ClsContactGroupsを作成します。TABLENAMEを実装するように求められます。ここでデータを取得します。例:TABLENAME = "contactgroups";
  • 2番目のクラスclsContactsを作成し、TABLENAMEを実装するように求められます。ここでデータを取得します。例:TABLENAME = "contacts";
    等...
43
Pentium10

あなたの混乱はC#のプロパティ対フィールド/変数にあると思います。 C#では、抽象クラスであっても抽象フィールドを定義できません。ただし、これらは事実上メソッドであるため、抽象プロパティを定義できます(たとえば、get_TAG()およびset_TAG(...)にコンパイルされます)。

一部の人が思い出したように、C#であっても、クラスにパブリックフィールド/変数を含めることはできません。いくつかの答えは、私がお勧めすることを暗示していますが、明確にしていません。 getTAG()を使用して、アイデアをJavaBeanプロパティとしてJavaに変換する必要があります。サブクラスはこれを実装する必要があります(これを行うテーブルクラスを使用してプロジェクトを作成しました) 。

したがって、このように定義された抽象クラスを持つことができます...

_public abstract class AbstractTable {

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

    ...
}
_

次に、具体的なサブクラスでは、静的な最終変数(定数)を定義し、getTag()から次のように返す必要があります。

_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 [〜#〜]

継承されたフィールドをオーバーライドすることはできません(C#またはJava)。また、静的メンバーは、フィールドであれメソッドであれ、オーバーライドできません。したがって、これもそのための最良のソリューションです。上記のinitメソッドの例を変更して、これがどのように使用されるかを示しました。再び、getXXXメソッドをプロパティと考えてください。

48
Kevin Brock

具象実装がコンストラクターの呼び出し/オーバーライドに必要な仕様に従っているようにフィールドを設定する抽象クラスでコンストラクターを定義します。

例えば。

_public abstract class AbstractTable {
    protected String name;

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

AbstractTableを拡張すると、super("somename")を呼び出すコンストラクターを追加するまで、クラスはコンパイルされません。

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

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

このように、実装者はnameを設定する必要があります。この方法では、抽象クラスのコンストラクターで(null)チェックを実行して、抽象クラスをより堅牢にすることもできます。例えば:

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

Java(またはC++)の抽象変数のようなものはありません。

親クラスに変数があり、子クラスが親を拡張する場合、子は変数を実装する必要がありません。親のインスタンスにアクセスするだけです。取得/設定または保護されたアクセスのいずれかが行います。

「...だから、アブストラクトを実装するように促されるべきだ」抽象クラスを拡張し、抽象メソッドの実装に失敗した場合、コンパイラはそれを実装するか、サブクラスを抽象としてマークするように指示します。それはあなたが得るすべてのプロンプトです。

7
duffymo

このメソッドを基本クラスに追加するだけです

public abstract class clsAbstractTable {

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

}

これで、基本クラスを拡張する(そして抽象になりたくない)すべてのクラスがTAGを提供するはずです

また、BalusCの答えで行くこともできます

2
Lombo

最善の方法は、変数のアクセサー/ミューテーターを持つことです。
次のようなものgetTAG()
そのように、すべての実装クラスはそれらを実装する必要があります。

抽象クラ​​スは、データではなく抽象的な動作を定義するために使用されます。

2
Padmarag

すべてのサブクラスで変数を定義する必要があるのはなぜですか?すべてのサブクラスがそれを持つことになっている場合は、スーパークラスで定義するだけです。ところで、OOPとにかくフィールドを公開しないように練習すると、あなたの質問はさらに意味がなくなります。

1

コードを次のように変更します。

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

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

そうすれば、このクラスを継承するすべてのクラスにこの変数が設定されます。 200個のサブクラスを実行できますが、それでも各サブクラスにはこの変数があります。

サイドノート:変数名としてCAPSを使用しないでください。一般的な知恵は、すべてのキャップ識別子が定数、つまり変更不可能なデータを参照することです。

1
dimitarvp

クラスごとのメタデータを追加するには、注釈が正しい方法かもしれません。

ただし、静的メンバーまたは特定のコンストラクターの存在を強制できないのと同様に、インターフェイスに注釈の存在を強制することはできません。

1
Joachim Sauer

変数の実装はないため、抽象化することはできません;)

1
Tomas Vana

私の実験では、Java抽象クラスはabstractキーワードを指定する必要があります。逆に、「抽象修飾子をここに配置できません」というエラーが表示されます。通常の属性と同様の属性。

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

サブクラスでは、これらの属性を直接使用できますthis.flyBehaviorまたはthis.attackBehavior。属性フィールドの属性を書き換える必要はありません。

0
Shark Deng

列挙型を使用して値を強制し、バインドされたチェックを維持します。

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