Java 抽象类中的静态方法
我想这样定义一个抽象方法:Java 抽象类中的静态方法,java,oop,inheritance,static,Java,Oop,Inheritance,Static,我想这样定义一个抽象方法: public abstract class Saveable { public Set<Field> getFieldSet(); ... } 公共抽象类可保存{ 公共集getFieldSet(); ... } 无论对象的状态如何,getFields()都应始终返回相同的输出。但是,我不能将其声明为静态方法,因为我希望它被重写。现在我正在实现一个类User,它扩展了Saveable,并且它有一些需要字段集的静态方法。很明显,我拿不到它,
public abstract class Saveable {
public Set<Field> getFieldSet();
...
}
公共抽象类可保存{
公共集getFieldSet();
...
}
无论对象的状态如何,
getFields()
都应始终返回相同的输出。但是,我不能将其声明为静态方法,因为我希望它被重写。现在我正在实现一个类User
,它扩展了Saveable
,并且它有一些需要字段集的静态方法。很明显,我拿不到它,因为我没有物体。关于允许我在静态方法中获取字段的设计有什么想法吗?不幸的是继承的类不能覆盖静态方法,但它可以通过声明具有相同签名的静态方法来隐藏它
如果您的最终目的是在
Saveable
类中的另一个继承方法中使用GetFields()
,则这对您没有帮助,因为它将始终调用Saveable.GetFields()
,不是扩展类中的静态方法。您可以将当前方法保留为非静态且抽象的可保存方法,并返回非静态实现的静态集合
public class User extends Savable {
public static Set<AField> aSet = new HashSet<AField>();
@Override
public Set<? extends Field> getFields() {
return aSet;
}
}
公共类用户扩展可存储{
public static Set aSet=new HashSet();
@凌驾
publicset一种方法是通过将正确对象的实例传递给静态方法,然后对该对象调用getFields
,从而“伪造”该引用
另一个选项是将字段列表存储在类的静态字段中。重写的getFields()
实现可以返回它(或者最好是它的副本),静态方法可以直接访问它
我更倾向于实现后一个选项,因为它不那么笨拙(因为你永远不必重新创建一个无用的对象来传递给静态方法)。此外,它捕获了这样一个想法,即类的字段不依赖于给定的实例。当调用静态方法时,你调用的是类的名称作为作用域
因此,实际上没有覆盖的意义,你只是在隐藏它
此外,由于同样的原因,它不能被继承,因为它属于类类型,而不是类实例
最好是在派生类中调用基类的静态方法,并使用相同的方法名。扩展@dlev的答案,将字段存储在一个哈希映射中,该哈希映射由每个类的唯一标识符设置
如果您使用的是Spring,那么您可以在每个对象中注入字段集。因此,只有引用会被复制。这是我的建议,我得出结论。但是您必须以某种方式命名派生类名,在加载这些字段时,除了声明静态方法之外,没有其他方法
public abstract class Saveable {
public static Set<? extends Field> getFields(Class<? extends Saveable> clazz) {
return FieldsProvider.get(clazz);
}
}
public class FieldsProvider {
private static final Map<Class<? extends Saveable>, Set<? extends Field>> map =
new HashMap<Class<? extends Saveable>, Set<? extends Field>>();
public static void registerFields(Class<? extends Saveable> clazz, Collection<? extends Field> col) {
Set<? extends Saveable> set = new HashSet<? extends Saveable>();
set.addAll(col);
map.put(clazz, set);
}
public static Set<? extends Field> getFieldSet(Class<? extends Saveable> clazz) {
Set<? extends Field> set = map.get(clazz);
if (set != null) {
return set;
}
return Collections.emptySet();
}
}
public class User extends Saveable {
static {
FieldsProvider.registerFields(User.class, new HashSet<? extends Field>... ;
}
static void someMethod() {
Set<? extends Field> fieldsSet = getFields(User.class);
...
}
}
公共抽象类可保存{
公共静态集他知道这一点,因为他说“但是,我不能将其声明为静态方法,因为我希望它被重写。”这不是一个有用的答案。它们是继承的,但不是虚拟iirc。@如果您有specificsavable扩展Saveable
和getFields()
将是静态的,SpecificSaveable.getFields()
有效吗?是的,谢谢,我阅读了文档,我将更新我的答案。鉴于您明确指出“getFields()
应该始终返回相同的输出,而不管对象的状态如何”,它们引用的字段可能应该是静态的(可能是最终的)无论如何。如果您确实需要额外的分离,您可以编写一个额外的、静态的,getFields()
方法,您可以调用非静态版本(和其他静态方法)。否则,我可能会选择@dlev提供的答案。