Reputation: 79615
I want to define an abstract method like so:
public abstract class Saveable {
public Set<Field> getFieldSet();
...
}
getFields()
should always return the same output regardless of the object's state. However, I can't declare this as a static method because I want it to be overridden. Now I'm implementing a class User
which extends Saveable
and it has some static methods which require the field set. Obviously, I can't get it because I don't have an object. Any idea on a design that would allow me to get the fields in a static method?
Upvotes: 3
Views: 7672
Reputation: 24910
You can leave your current method as non-static and abstract in Savable and return a static Set out of the non-static implementation.
public class User extends Savable {
public static Set<AField> aSet = new HashSet<AField>();
@Override
public Set<? extends Field> getFields() {
return aSet;
}
}
Upvotes: 1
Reputation: 1507
This is the proposal, I worked out. But you somehow have to name the derived class name, when loading those fields, there is no other way around, apart from declaring the methods static anyway.
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);
...
}
}
Upvotes: 0
Reputation: 48596
One approach would be "fake" the this
reference by passing in an instance of the correct object to the static methods, and then calling getFields
on that object.
Another option is to store the field list in a static field on the class. Your overridden getFields()
implementation can return it (or preferably a copy of it,) and your static methods can access it directly.
My preference would be to implement the latter option, as it's a lot less clumsy (since you never have to new up an otherwise useless object to pass in to the static methods.) As well, it captures the idea that the class's fields don't rely on a given instance.
Upvotes: 4
Reputation: 1039
Expanding @dlev 's answer, how about you store the fields in a hashmap keyed off by unique identifier per class.
If you are using Spring, you can inject the set of fields in every object. Hence only the reference will be duplicated.
Upvotes: 0
Reputation: 11308
Unfortunately an inherited class can't override a static method, but it can hide it by declaring an static method with the same signature.
This will not help you if your final purpose is to use the GetFields()
inside another inherited method in the Saveable
class, because it will always call Saveable.getFields()
, not the static method in your extending class.
Upvotes: 1
Reputation: 49221
When calling a static method, you're calling the class' name as a scope.
So there's actually no meaning of overriding, you're only hiding it anyway.
Besides, because of the same reason, it cannot be inherited because it belongs to the class type, not a class instance.
The best you can do is call the base class' static method in the derived class, and have the same method name.
Upvotes: 0