0

Sometimes there is a demand for inherit a singleton but because in singleton you are using a static reference and static method that cannot be overridden.

For example (Java):

public class Singleton {
    private static Singleton instance = null;

    public static Singleton getInstance() {
        if (instance == null)
            instance = new Singleton();
        return instance;
    }
}

If i would inherit "Singleton" with "SingletonChild" class i won't be able to generate an instance by calling getInstance() method. If i will create another getInstanceChild() method the base method: getInstance() also will be exposed.

karthikr
  • 87,486
  • 24
  • 182
  • 182
Kvant
  • 1,407
  • 17
  • 18
  • 2
    A true singleton will typically need to have a `private` constructor. You won't be able to extend that class. – Sotirios Delimanolis Jan 07 '15 at 16:25
  • 1
    Singletons also cause more problems that they solve, which is why it's considered an anti-pattern under most circumstances. See [this post](http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons). Adding inheritance to it makes it worse IMHO. – Invisible Arrow Jan 07 '15 at 16:30
  • 3
    The idea of a singleton is that there is only one in your system. When you inherit from a class, your object is still an instance of the parent class (polymorphically). So a second instance of it would violate the singleton contract. Perhaps you should consider what you really need, instead of a singleton. – RealSkeptic Jan 07 '15 at 16:35
  • Consider this: you are writing some library that have some global functionality as singleton that should be extended according the target usage. – Kvant Jan 07 '15 at 17:38
  • Related question: http://stackoverflow.com/q/23170221/1168342 – Fuhrmanator Jan 08 '15 at 13:43

2 Answers2

1

You can use the Adapter pattern and wrap the singleton with another Object. If you also have the Singleton and the Adapter share an interface, then the calling code doesn't have to know which one is being passed around.

interface MyInterface{
    String foo();

    void bar();
}

public class Singleton implements MyInterface{
  //..same as before

}


public class Adapter implements MyInterface{
     private MyInterface delegate;

     public Adapter(MyInterface adaptMe){
        //check for null in real code
        this.delegate = adaptMe;
     }

     //delegate to bar
     public void bar(){
         delegate.bar();
     }

     //override foo
     public String foo(){
        return "AdaptedFoo";
     }
}

then your code can wrap the Singleton

MyInterface myInterface = new Adapter(Singleton.getInstance());
dkatzel
  • 29,286
  • 2
  • 57
  • 64
  • 1
    This is indeed correct solution, but in such solution you will have to implement and support every single method in a base class which is not very convenient. – Kvant Jan 07 '15 at 17:28
  • 1
    Yes, that is true. There are some tricks you can do with Java to use reflection to delegate calls see the Oracle Tutorial on Dynamic Proxies http://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html – dkatzel Jan 07 '15 at 18:24
0

One way is to use a separated factory that will be a creator such classes and insure that they are singles indeed. But there is a different problem with this solution, the factory has to know about every implementation of class that uses base 'Singleton' or this factory have to be extended in order to obtain such knowledge.

There is a different approach that will solve this issue and let you inherit singleton with new implementation without modifications of a factory.

public abstract class SingletonInheritance {
    public static abstract class AbstractSingleton {
        private static AbstractSingleton instance = null;

        protected AbstractSingleton() {
        }

        public static <T extends Class<? extends AbstractSingleton>>
        AbstractSingleton getInstance(T _class) {
            if (instance == null) {
                try {
                    instance = _class.getDeclaredConstructor().newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            }
            return instance;
        }
    }

    public static class Singleton extends AbstractSingleton {
        public String foo() {
            return "Singleton";
        }
    }

    public static class SingletonChild extends Singleton {
        @Override
        public String foo() {
            return "SingletonChild";
        }
    }

    public static void main(String[] args) {
        SingletonChild singletonChild = 
            (SingletonChild) SingletonChild.getInstance(SingletonChild.class);
        System.out.println(singletonChild.foo());
    }
}

Output: "SingletonChild"

wassgren
  • 16,439
  • 5
  • 53
  • 71
Kvant
  • 1,407
  • 17
  • 18