我有以下类,我将其用作项目中所有模型的基础:
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 = ?”。因此,覆盖 table
类中的 User
字段似乎没有任何效果。
我该如何克服这个问题?如果我在 BaseModel 中添加了一个
setTable()
方法,并在 setTable()
的构造函数中调用 User
,那么 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
的限制。
(注意,你还需要使用方法,因为字段不参与多态性,因此不能被重写)
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
为了完成您想要做的事情,请勿将
table
设为静态 BaseModel
。然后在继承自 BaseModel
的其他类中,您可以在默认构造函数中将 table
设置为您想要的任何值。
static {
table = "user";
}
我是一名拥有 3 年经验的 Python 开发人员,目前正在学习 Java。我正在按如下方式解决这个问题,但我相信它可能有更好的解决方案。
Main.java
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person burakhan= new Person("Burakhan", 28);
Person fatma = new Person("Fatma", 25);
EnglishPerson david = new EnglishPerson("David", 22);
GermanPerson bruno = new GermanPerson("Bruno", 23);
Group group = new Group();
group.addToGroup(burakhan);
group.addToGroup(fatma);
group.addToGroup(david);
group.addToGroup(bruno);
group.members();
}
public class Person {
String name;
int age;
static String country = "TR"; // default
public Person(String name, int age){
this.name = name;
this.age = age;
}
public void getOlder(){
this.age++;
}
public void speak() throws NoSuchFieldException, IllegalAccessException {
String sentence = "My name is %s and I am %d years old. I am from %s".formatted(this.name, this.age, getClass().getDeclaredField("country").get(this));
System.out.println(sentence);
}
}
EnglishPerson.java
package person;
public class EnglishPerson extends Person {
static String country = "UK";
public EnglishPerson(String name, int age) {
super(name, age);
}
}
德国人.java
package person;
public class GermanPerson extends Person {
static String country = "GER";
public GermanPerson(String name, int age) {
super(name, age);
}
}
当我运行主程序时,它看起来像这样。
My name is Burakhan and I am 28 years old. I am from TR
My name is Fatma and I am 25 years old. I am from TR
My name is David and I am 22 years old. I am from UK
My name is Bruno and I am 23 years old. I am from GER
再说一遍,我也在学习Java,我相信这种方法有点Pythonic。喜欢听听其他意见