60

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

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

public abstract class clsAbstractTable {

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

}

しかし、Eclipseは私が不正な修飾子を使用していると言っています。

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

public class clsContactGroups extends clsAbstractTable {


}

Eclipseがプロンプトを表示するように変数とメソッドを定義したいのですが、実装されていない抽象変数とメソッドがあります。

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

編集1

データベーステーブルごとに異なるクラスを作成します。各クラスには、例外なく、独自の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";
    等...
4

13 に答える 13

63

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

例えば

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;
}
于 2010-03-03T12:14:57.310 に答える
53

あなたの混乱は、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();
        ...
    }

}

編集

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

于 2010-03-03T12:49:46.380 に答える
11

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

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

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

于 2010-03-03T12:14:31.910 に答える
3

あなたができる最善のことは、変数のアクセサー/ミューテーターを持つことです。getTAG()
のようなもの このように、すべての実装クラスはそれらを実装する必要があります。抽象クラスは、データではなく抽象動作を定義するために使用されます。


于 2010-03-03T12:15:27.947 に答える
2

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

public abstract class clsAbstractTable {

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

}

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

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

于 2010-03-03T12:15:03.547 に答える
1

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

于 2010-03-03T12:13:31.413 に答える
1

すべてのサブクラスで変数を定義するのはなぜですか?すべてのサブクラスにそれがあるはずの場合は、スーパークラスで定義するだけです。ところで、とにかくフィールドを公開しないのは良いOOPプラクティスであることを考えると、あなたの質問はさらに意味がありません。

于 2010-03-03T12:17:10.673 に答える
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を使用しないでください。一般的な知恵は、すべてのキャップ識別子が定数、つまり変更できないデータを参照することです。

于 2010-03-03T12:19:49.110 に答える
1

クラスごとのメタデータを追加するには、アノテーションが正しい方法かもしれません。

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

于 2010-03-03T13:02:47.687 に答える
0

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

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);
    }
}
于 2018-12-02T00:25:12.363 に答える
0
public abstract class Duck 
{
    /** This is not static. */
    private String duckName = "";

    /** Abstract Constructor. */
    public Duck(final String name) 
    {
        duckName = name;
    }

    /** Accessor method. */
    public String getName()
    {
         return duckName;
    }

    /** An example of an abstract method that has to be made concrete. */
    public abstract void fly(); 

}

次に、別のクラスがあります。

public class KhakiCampbell extends Duck
{
    // Constructor
    public KhakiCampbell(final String name)
    {
        super(name);
    }

    @Override
    public void fly()
    {
        /** Do something simple. */
       System.out.println(getName() + " is flying!");
    }
 
    /** This is something that only Khaki Cambell ducks do, of course, joke!. */
    public void crash()
    {
       /** Do something simple. */
       System.out.println(getName() + " has crashed!");
    }
 
    /** Keep going. */
    public void stillFly()
    {
        /** Do something simple. */
        System.out.println(getName() + " is still flying!");
    }

    public static void main(String[] args)
    {
        KhakiCampbell  duck = new KhakiCampbell("Bella");
        KhakiCampbell  mavis = new KhakiCampbell("Mavis");
        KhakiCampbell  boris = new KhakiCampbell("Boris");
        duck.fly();
        mavis.fly();
        boris.crash();
        mavis.stillFly();
    }
}

もちろん、上記のコードを Duck.java と KhakiCampbell.java の別々のファイル名に入れて実行しました。Eclipse で KhakiCampbell を実行した後、Java コンソールに次のように表示されました

メイビスが飛んでる!
ボリスが墜落した!
メイビスはまだ飛んでいます!

これがあなたの質問に答えることを願っています。静的変数宣言は必要ありません。

于 2022-01-18T14:15:01.677 に答える
-1

いいえ、Javaは抽象変数をサポートしていません。それもあまり意味がありません。

サブクラスに期待される変数の「実装」に対する具体的な変更は何ですか?

基本クラスに変数があるabstract String場合、それを非抽象にするためにサブクラスは何をすべきですか?

于 2010-03-03T12:13:38.153 に答える