简体   繁体   中英

protected static member for inherited class

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 (ie 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());
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM