簡體   English   中英

Java:覆蓋父類的靜態變量?

[英]Java: Overriding static variable of parent class?

我有以下類,我將其用作項目中所有模型的基礎:

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 = ?" ,它正在生成查詢:“SELECT id from null WHERE id = ?”。 因此,覆蓋User類中的table字段似乎沒有任何效果。

我該如何克服呢? 如果我在 BaseModel 中添加了一個setTable()方法,並在User的構造函數中調用了setTable() ,那么table的新值是否也可用於User類的所有方法?

您不能覆蓋 Java 中任何類型的靜態方法或字段。

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

這將創建一個新字段User#table恰好與BaseModel#table同名。 大多數 IDE 都會對此發出警告。

如果您更改 BaseModel 中字段的值,它也將應用於所有其他模型類。

一種方法是讓基本方法通用

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 (每個模型類一個)。 然后創建所有 daos 的單例實例。

因為 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

為了做你想做的事,不要在BaseModel中使table成為靜態的。 然后在從BaseModel繼承的其他類中,您可以將默認構造函數中的table設置為您想要的任何內容。

static {
    table = "user";
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM