2013-10-18 59 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 –