web-dev-qa-db-ja.com

Java:親クラスの静的変数をオーバーライドしますか?

私のプロジェクトのすべてのモデルのベースとして使用している次のクラスがあります。

_public abstract class BaseModel
{
    static String table;
    static String idField = "id";       

    public static boolean exists(long id) throws Exception
    {
        Db db = Util.getDb();
        Query q = db.query();
        q.select( idField ).whereLong(idField, id).limit(1).get(table);

        return q.hasResults();
    }

    //snip..
}
_

それから、次の方法でそれから拡張しようとしています:

_public class User extends BaseModel
{
    static String table = "user";
    //snip
}
_

ただし、次のことをしようとすると:

_if ( User.exists( 4 ) )
   //do something
_

次に、クエリ__"SELECT id FROM user WHERE id = ?"_ではなく、クエリ "NULLからのidの選択WHERE WHERE =?"を生成します。そのため、tableクラスのUserフィールドをオーバーライドしても効果はないようです。

どうすればこれを克服できますか? setTable()メソッドをBaseModelに追加し、UserのコンストラクターでsetTable()を呼び出すと、tableの新しい値が利用可能になりますUserクラスのすべてのメソッドも同様ですか?

17
Click Upvote

Javaでは、任意のタイプの静的メソッドまたはフィールドをオーバーライドできません。

public class User extends BaseModel
{
    static String table = "user";
    //snip
}

これにより、User#tableと同じ名前を持つ新しいフィールドBaseModel#tableが作成されます。ほとんどのIDEはそれについて警告します。

BaseModelのフィールドの値を変更すると、他のすべてのモデルクラスにも適用されます。

1つの方法は、基本メソッドをジェネリックにすることです

protected static boolean exists(String table, long id) throws Exception
{
    Db db = Util.getDb();
    Query q = db.query();
    q.select( idField ).whereLong(idField, id).limit(1).get(table);

    return q.hasResults();
}

サブクラスで使用します

public static boolean exists(long id)
{
    return exists("user", id);
}

フィールドアプローチを使用する場合は、BaseDAOクラスを作成し、それに応じてフィールドを設定するUserDAO(モデルクラスごとに1つ)を作成する必要があります。次に、すべてのdaosのシングルトンインスタンスを作成します。

16
Cephalopod

Javaではstaticのメンバーをオーバーライドすることはできないため、基本的には少し冗長で全体的に優れた シングルトンパターン に頼る必要があります。概念的には「静的」コードを記述していますが、技術的には(global/singleton /「static」)インスタンスを使用しているため、staticの制限による制限を受けません。

(フィールドはポリモーフィズムに関与しないため、オーバーライドできないため、メソッドを使用する必要があることに注意してください)

public abstract class BaseTable {
    public abstract String table();
    public String idField() { return "id"; }

    public boolean exists(long id) {
        // don't build queries this way in real life though!
        System.out.println("SELECT count(*) FROM " + table() + " WHERE " + idField() + " = " + id);
        return true;
    }
}

public class UserTable extends BaseTable {
    public static final User INSTANCE = new UserTable();
    private UseTabler() {}

    @Override public String table() { return "user"; }
}

public class PostTable extends BaseTable {
    public static final Post INSTANCE = new PostTable();
    private PostTable() {}

    @Override public String table() { return "post"; }
}

public static void main(String[] args) {
    UserTable.INSTANCE.exists(123);
    PostTable.INSTANCE.exists(456);
}

出力:

SELECT count(*) FROM user WHERE id = 123
SELECT count(*) FROM post WHERE id = 456
9
Erik Allik

目的の処理を実行するために、tableBaseModelを静的にしないでください。次に、BaseModelを継承する他のクラスで、デフォルトコンストラクターのtableを任意の値に設定できます。

static {
    table = "user";
}
3
Brian Dishaw