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 = ?"
,它正在生成查询:“SELECT id from null WHERE id =?”。 因此,覆盖User
类中的table
字段似乎没有任何效果。
我该如何克服这个问题? 如果我将一个setTable()
方法添加到BaseModel,并在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
成员,所以你基本上需要采用稍微更冗长但整体更好的单例模式 ,其中你仍然在概念上编写“静态”代码,但你在技术上使用(全局/单例) /“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
inheritance的其他类中,您可以将默认构造函数中的table
设置为您想要的任何内容。
static { table = "user"; }