2013-10-18 97 views
11

我有以下類我使用所有的車型在我的項目基地: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 = ?",它生產的問題:「從空選擇ID其中,ID = ?」。因此,User類中的table字段的重寫似乎沒有任何效果。

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

+1

點擊了給予好評,在答案太。 – UDPLover

回答

12

您不能覆蓋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的單例實例。

+1

爲什麼IDE會警告數據隱藏? –

+0

@點擊:我擴展了我的答案。 – Cephalopod

+0

'exists()'只是一個例子,我有另外10-20個這樣的輔助方法。我不想重載所有它們,我寧願只更改表名稱屬性,以使它們都能正常工作。 –

2

爲了做你正在做的事情,不要讓table靜態在BaseModel。然後在繼承自BaseModel的其他類中,可以將默認構造函數中的table設置爲任何所需的值。

static { 
    table = "user"; 
} 
+1

然後我不能調用'User.exists()'作爲靜態方法。 –

+0

@ClickUpvote這可能表示您濫用了'static'關鍵字。我建議看看你的設計,並重新設計它以擺脫對靜態存在()方法的需求 – StormeHawke

+0

@StormeHawke我的設計出了什麼問題?如果我只是爲了檢查給定的用戶標識是否有效而創建了我的用戶模型實例,它會更清晰嗎? –

8

因爲Java不允許您覆蓋static會員,你基本上需要訴諸稍微詳細,但整體更好singleton pattern,其中你還在寫概念「靜態」的代碼,但你技術上使用(全局/單例/「靜態」)實例,所以您不受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 
+0

下面是它在Scala中的樣子,加入了一些天真的反射,沒有單獨的樣板:http://pastebin.com/3iujwygZ –