Cli*_*ote 18 java oop static static-members
我有以下类,我正在使用它作为我项目中所有模型的基础:
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..
}
Run Code Online (Sandbox Code Playgroud)
我正试图通过以下方式扩展它:
public class User extends BaseModel
{
static String table = "user";
//snip
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试执行以下操作:
if ( User.exists( 4 ) )
//do something
Run Code Online (Sandbox Code Playgroud)
然后,而不是查询:"SELECT id FROM user WHERE id = ?",它产生查询:"SELECT id from null WHERE id =?".因此,类中table字段的覆盖User似乎没有任何影响.
我该如何克服这个问题?如果我setTable()向BaseModel 添加了一个方法,并setTable()在构造函数中调用User,那么新值table是否也可用于User该类的所有方法?
Cep*_*pod 17
您不能在Java中覆盖任何类型的静态方法或字段.
public class User extends BaseModel
{
static String table = "user";
//snip
}
Run Code Online (Sandbox Code Playgroud)
这会创建一个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();
}
Run Code Online (Sandbox Code Playgroud)
并在子类中使用它
public static boolean exists(long id)
{
return exists("user", id);
}
Run Code Online (Sandbox Code Playgroud)
如果要使用字段方法,则必须创建一个BaseDAO类并具有UserDAO(每个模型类一个)相应地设置字段.然后,您创建所有daos的单例实例.
因为Java不允许你覆盖static成员,所以你基本上需要采用稍微更冗长但整体更好的单例模式,其中你仍然在概念上编写"静态"代码,但是你在技术上使用(global/singleton/"静态")实例,所以你不受限制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);
}
Run Code Online (Sandbox Code Playgroud)
输出:
SELECT count(*) FROM user WHERE id = 123
SELECT count(*) FROM post WHERE id = 456
Run Code Online (Sandbox Code Playgroud)
为了执行您想要执行的操作,请勿table在BaseModel. 然后在继承自 的其他类中BaseModel,您可以table在默认构造函数中设置您想要的任何内容。
static {
table = "user";
}
Run Code Online (Sandbox Code Playgroud)