Java:重写父类的静态变量?

问题描述 投票:0回答:4

我有以下类,我将其用作项目中所有模型的基础:

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 oop static static-members
4个回答
27
投票

您不能覆盖 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 的单例实例。


12
投票

因为 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

5
投票

为了完成您想要做的事情,请勿将

table
设为静态
BaseModel
。然后在继承自
BaseModel
的其他类中,您可以在默认构造函数中将
table
设置为您想要的任何值。

static {
    table = "user";
}

0
投票

我是一名拥有 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。喜欢听听其他意见

© www.soinside.com 2019 - 2024. All rights reserved.