I have a few classes that all inherit the same base class and need to have a static property that is initialized in a function at startup. I implemented it this way:
public abstract class Base {
protected static Model model;
}
public class Inherited extends Base {
static {
model = initializationFunction();
}
}
public class OtherInherited extends Base {
static {
model = otherInitializationFunction();
}
}
// Example of use
Base[] inheriteds = new Base[] { new Inherited(), new OtherInherited() };
for (int i = 0; i < inheriteds.length; i++) {
doStuff(inheriteds[i]).model; // This will always use the same model (last defined)
}
So the class initializes the static member at start. But it appears that it sets the value of model for the whole base class, and so all classes actually have the same model.
I need model to be static because the it needs to exist only once per subclass. My problem is how to have one static model per subclass, while still ensuring it is defined in the parent class (so if a class doesn't define it, it is defined in the parent class).
What is the expected behaviour of a protected static member in an inherited class? And how should I go about having my version of this member for each class, still static (I don't want it to duplicate for each instance)?
My problem is how to have one static model per subclass, while still
ensuring it is defined in the parent class (so if a class doesn't
define it, it is defined in the parent class).
No way, Because, static members and polymorphism, inheritance don't go together
Inheritance does not work for static fields (i.e. class fields). So there is only one single field Base.model. Inherited.model refers to the same field.
If you really need the resolution of the model to be automatic instead of having the devoloper ensure consistency, then you need to implement the whole mechanism yourself because no language feature of Java will take care of that directly.
One of the options is going down the Singleton route, where the singleton would be the Model factory. Instead of accessing the static field directly to get the model, you would ask the respective class's factory singleton to get it. The factory itself would subclass the base factory, so then you can get the "automatic default" behavior by polymorphism.
As other answers have suggested, static members are scoped at the class level and not at the object level, and in short are not part of inheritance hierarchies whatsoever. The class name for a static member is just an extra namespace qualifier. Here is a pretty good synopsis on the static keyword: http://mindprod.com/jgloss/static.html
As for solving your problem, I took a crack at this while still using static members. If you really must have each instance of a subclass share the same model instance while maintaining some kind of interface compatibility with the base class then consider doing something like the following:
public abstract class Base {
public abstract Model getModel();
}
public class Inherited extends Base {
static private Model model = initializationFunction();
public Model getModel() {
return model;
}
}
public class OtherInherited extends Base {
static private Model model = otherInitializationFunction();
public Model getModel() {
return model;
}
}
The fact there are static members involved here is hidden from the interface, which is a big win all around. If you reach the point where you can solve this problem without using static members, the clients of your class hierarchy here will not be affected since accessing a model does not expose the implementation detail of the use static members at all.
Maybe managing the model objects somehow:
public abstract class TestBase {
private static Map<Class, Object> modelObjects = new HashMap<>();
public static void setModel(Class _class, Object model) {
modelObjects.put(_class, model);
}
public static Object getModel(Class _class) {
return modelObjects.get(_class);
}
public static class Inherited extends TestBase {
static {
setModel(Inherited.class, new Object());
}
}
public static class OtherInherited extends TestBase {
static {
setModel(OtherInherited.class, new Object());
}
}
}
Related
I have the following situation:
A parent class has a function that depends on a constant. But the only valid place to define that constant is in subclasses (parent class cannot define the constant's value, but it can be used with the constant undefined in 99% of use cases - the constant is a default to use if a specific configuration element is missing).
However, I would like to enforce that any child class inheriting from that parent class must define the value for the constant, since any child classes have to be able to use the other 1% of functionality.
What is the best practice to implement this enforcement in Java, ideally at compile time? (clearly, at runtime, I can simply check if the constant is null/empty in the method using it).
My own solution was to implement a value-getter for the constant as an abstract method in the parent class, and call that in combination with the real setter in the constructor; something like this:
public class HelperClass1 {
private String myConstant;
public void setMyConstant() {} // implemented obviousy
public void myMethod() { // Called from ParentClass's methods
// Do something useful with myConstant
}
}
import HelperClass1;
public abstract class ParentClass {
ParentClass() {
HelperClass1.setMyConstant( getMyConstantValue() );
}
public abstract void getMyConstantValue();
}
public class ChildClass1 extends ParentClass {
public void getMyConstantValue() { return "BUZZ"; }
}
public class ChildClass2 extends ParentClass {
} // Fails to compile without getMyConstantValue()
However, (a) This implementation has a problem (I can't use ParentClass itself, since it's now abstract) without subclassing; and (b) since I'm not a Java developer, I'm afraid that this isn't the best or the most elegant solution. So I'd like to know if there's a best practices approach that improves on what I implemented.
Provide two constructors for the parent class:
One is a protected constructor which takes the constant as an argument.
The other is private constructor which can construct instances of the parent class without setting the constant.
Provide a factory method for the parent class which can call the private no-constant constructor.
Classes that want to get an instance of the parent class can call the factory method. But child classes that want to inherit from the parent class have to call the protected constructer, which can validate that a valid constant was passed.
public class ParentClass {
private final SomeClass myConstant;
protected ParentClass(SomeClass aConstant) {
if (null == aConstant) {
throw new IllegalArgumentException("...");
}
myConstant = aConstant;
}
private ParentClass() {
myConstant = null;
}
public static ParentClass getInstance() {
return new ParentClass();
}
}
public class ChildClass {
public ChildClass() {
super(new SomeClass(42));
}
}
This isn't perfect. Someone could write a child class that passes a bad constant to the superclass constructor, and it wouldn't actually fail until some code tried to construct an instance of the child class.
We all know that in Java, if you declare a static method in a Abstract class, that method will belong to the Abstract class, and not to its child. (There is no abstract static)
I have a simple database system that has a Abstract Model class:
public abstract class Model<T> {
// WON'T WORK (unfortunately I can't use abstract static)
public static T find(int id) {
...
}
}
As you can see, I can't create a static method on that class that returns a generic, since that method is not inherited, so it belongs to the abstract class.
A workaround is to make a protected method on the abstract class and then a static method on each of its children:
public abstract class Model<T> {
protected T find(int id) {
...
}
}
public class User extends Model {
public static User find(int id) {
User dummy = new User();
return (User) dummy.find(id);
}
}
I feel that there are better ways of doing that.
Any ideas?
I can think of two possible options, although one is a bit of a hack. The first one would be to make Model<T> a normal class and adding a static method to get the model like this:
//I do not know how you want to do the user class, I just made it take the models class
private static final Model<User> MODEL = new Model<User>(User.class);
public static Model<User> model() {
return MODEL;
}
You would use it like this: User.model().find(id)
Another option would be to add a public static variable to the class and static importing that variable to invoke methods on it as if it were the class and not the Model instance. For example:
public class User {
public static Model<User> User = new Model<User>(User.class);
}
Importing it using static import my.package.User.User; would allow you to use User user = User.find(id); where the first User is the class name and the second User is the static variable.
Otherwise, you will have to put the static methods in each class, because unfortunately you cannot inherit or override them.
You could use a static generic method with a type that extends the parent class. You will, however, need an instance of the type in order to do the return of type T. The easiest way is to pass in the caller, but it could just be an empty instance.
For example, you can do the following:
//No more generic Model
public abstract class Model
{
//Our generic static method; we need caller to get something of type T to return.
public static <T extends Model> T find(int id, T caller)
{
...
return caller.getMyReturnObject(id);
}
}
To invoke this you would just do
Model model = find(someId, new Model{...})
where new Model{...} can be replaced by this if you invoke it within a class that is a child of Model.
If you need to create a new instance of T in the method, then you will still need to pass in something as T (the caller still works) and use reflection to create the new instance (using something like (T) type.getClass().newInstance(); instead of new T()).
I have a super class, SuperClass. I want a JList displaying every subclass of SuperClass. Not how many subclasses of SuperClass were instantiated, but how many subclasses I have actually defined in my program. The point is that it should be easy to add new subclasses without changing code anywhere else.
I'm hoping that my SuperClass can define a static map that would increase for every subclass I define (not instantiate). Now by clicking on the items of the JList the appropriate subclasses should be instantiated.
I will try to show what I want to do:
public abstract class SuperClass {
protected static ArrayList<?extends SuperClass> subclasses = new ArrayList<>();
}
class SubClassOne extends SuperClass {
static {
subclasses.add(this)
}
}
Now I realize there are lots of problems with above code, but I hope it clarifies what I want. I'm entirely clueless how I should proceed with regards to instantiating my subclasses from the JList.
Please specify if I can give any more information that could be of help.
As demonstrated by the other answers, it is not suited for inheritance. Rather look at the factory pattern: some factory class that holds (a map of) classes, and it can instantiate objects of one of those classes.
There are some standard mechanisms in Java.
You could make your own annotation; use annotation processing
#Factored
public class A {
}
#Factored
public class B {
}
This is a large coding overhead.
You could use the java service provider interface
This SPI is used for detecting XML parsers and such, where jars on the class path have a file under MANIFEST with a text file with a file name the interface class path.
In it one or more implementation classes may be listed. These implementations can then be listed.
This is a declarative approach, so lacks the desired automatism.
Make an enum of factories
Suitable only for a limited close-world set of classes, also giving strong dependencies.
public enum Factory<T> {
F_A(A.class),
F_B(B.class);
private static final Set<Class<T>> klasses = new HashSet<>();
static {
for (Factory f : values()) {
klasses.add(f.klass);
}
}
public final Class<T> klass;
private Factory(Class<T> klass) {
this.klass = klass;
}
//public <S extends T> S instantiate(Class<S> kl) {
public T instantiate() {
...
}
}
You can use a static initializer block in your subclasses:
public class MySubclass extends MySuperclass {
static {
MySuperclass.register(MySubclass.class);
}
}
then in your superclass you can have a register method like this:
protected static void reigster(Class<?> clazz) {
subclasses.add(clazz);
}
Then when you want to instantiate a class:
MySuperclass subclassInstance = subclasses.get(someIndex).newInstance();
Note that this only works if you actually load those classes. For dynamic class loading you might have to implement your own ClassLoader or use some dynamic OSGi framework like the Apache Felix.
Approach 1:
public abstract class SuperClass {
protected static ArrayList<Class<? extends SuperClass>> subclasses = new ArrayList<>();
}
class SubClassOne extends SuperClass {
static {
subclasses.add(SubClassOne.class);
}
}
Approach 2
Scan entire classpath (using reflection), iterate for each class and check if the class inherits from your superclass.
You could look into Reflections library. I'd do it for you in an easy way.
Hope this helps.
I have a series of classes, A,B,C... (several dozen in total) that share common code. There can be many instance of each class A,B,C... . I'm planning to create a superclass, Abstract, that will contain that code instead.
Problem is, the common stuff works on an object that is unique on a per-class (not per-instance) basis. This is currently solved by A,B,C... each having a static field with the corresponding value. Obviously, when I refactor the functionality into Abstract, this needs to be changed into something else.
In practice, it currently looks like this (note that the actual type is not String, this is just for demonstrative purposes) :
public class A implements CommonInterface {
private static final String specificVar = "A";
#Override
public void common() {
specificVar.contains('');
}
}
public class B implements CommonInterface {
private static final String specificVar = "B";
#Override
public void common() {
specificVar.contains('');
}
}
The best idea I've come up with until now is to have a Map<Class<? extends Abstract>,K> (where K is the relevant type) static field in Abstract, and A,B,C... each containing a static initalization block that places the relevant value into the map. However, I'm not convinced this is the best that can be done.
Note that I'm not using any DI framework.
So, what would be the most concise, in terms of code contained in the subclasses, way to refactor the static fields in A,B,C... handled by the common code, without sacrificing field access efficiency?
Perhaps an enum is what you want.
enum MyInstances implements MyInterface {
A {
fields and methods for A
}, B {
fields and methods for B
};
common fields for all MyInstances
common methods for all MyInstances
}
// To lookup an instance
MyInstances mi = MyInstances.valueOf("A");
As you haven't shown any source code, we can't really tell if the use of static fields is a good or a bad design choice.
Considering the use of static fields by the subclasses is indeed a good design choice, the first way of having common code in a superclass to access them is by calling abstract methods that would be implemented in the subclasses.
Example:
public abstract class SuperClass {
public void processCommonLogic() {
// Common logic
// Execute specific logic in subclasses
processSpecificLogic();
}
public abstract void processCommonLogic();
}
public class ASubClass extends SuperClass {
public static int SPECIFIC_SUBCLASS_CONSTANT = 0;
public void processSpecificLogic() {
// Specific subclass logic
doSomethingWith(ASubClass.SPECIFIC_SUBCLASS_CONSTANT);
}
}
You could use the Template Method Pattern.
Have an abstract method getValue() defined in your abstract class and used within your abstract class wherever you require the value. Then each of your subclasses simply need to implement the getValue method and return the correct value for that subclass.
I have inherited a particular class hierarchy of singletons whose declarations are summarized below (there are more implementations -- I'm just showing the minimal set to demonstrate the problem). It smells to high heaven to me, foremost because singletons are being inherited from, as well as the way instance in the base class has its value overwritten in the static initializers of the subclasses.
If all the implementations were in the foo.common parent package I would consider just dropping the instance member and getInstance() methods from them, making the classes and their constructors package-local, and having some public factory class in foo.common create a single instance of each, hold onto that single instance of each internally (partitioned by whether it was an implementation of IReadOnly or IReadWrite) and provide a couple of public lookup methods where based on some enum it would return the asked-for implementation as the interface type.
But implementations can be outside of foo.common and foo.common isn't allowed to depend on such "more specific" packages, since foo.common is intended for stuff common to a bunch of apps. So something that simple can't be done. What then?
First interface:
package foo.common.config;
public interface IReadOnly
{
void load();
String getVal(String key);
}
Second interface:
package foo.common.config;
public interface IReadWrite extends IReadOnly
{
void save();
void setVal(String key, String value);
}
First implementation:
package foo.common.config;
public class ReadOnlyImpl implements IReadOnly
{
protected static IReadOnly instance;
static {
instance = new ReadOnlyImpl();
}
public static IReadOnly getInstance() {
return instance;
}
protected ReadOnlyImpl() {}
// implement methods in IReadOnly
}
Second implementation
package foo.common.config;
public class ReadWriteImpl extends ReadOnlyImpl implements IReadWrite
{
static {
instance = new ReadWriteImpl();
}
public static IReadWrite getInstance() {
return (IReadWrite) instance;
}
protected ReadWriteImpl() {
super();
}
// Implement methods in IReadWrite
}
Third implementation:
// While things in this package can depend
// on things in foo.common, nothing in
// foo.common is allowed to depend on this package.
package foo.apps.someapp;
public class MoreSpecificReadWriteImpl extends ReadWriteImpl
{
static {
instance = new MoreSpecificReadWriteImpl();
}
public static IReadWrite getInstance() {
return (IReadWrite) instance;
}
protected MoreSpecificReadWrite() {
super();
}
// Override superclass methods to do something specific
}
Putting package foo.apps.someapp aside, the design of the package foo.common.config is wrong.
IReadOnly o1=ReadOnlyImpl.getInstance(); // ok, returns ReadOnlyImpl
...
ReadWrite o2=ReadWriteImpl.getInstance(); // ok, returns ReadWriteImpl
...
IReadOnly o3=ReadOnlyImpl.getInstance(); // bad, returns ReadWriteImpl, the same as o2.
The reason is that all classes use the same static variable ReadOnlyImpl.instance. I would use separate variable in all classes, including MoreSpecificReadWriteImpl. If this would not fit, then think of using Spring container or similar framework.