7

What I'd like to do is just make a class that when you extend it, you automatically get the getInstance class. The problem is, when i extend it, I can't reference the child class. The only way I could see to do it is by typecasting ((ClassName)class.getInstance()) but its not very user-friendly. Any suggestions?

Arhowk
  • 881
  • 4
  • 11
  • 21
  • 1
    This is another reason why Singletons are not meant to use in real world applications. If you want something like that, you must create an static method on every class that extends the Singleton parent class since `static` methods can't be inherited. – Luiggi Mendoza Apr 29 '13 at 02:33
  • Could you post what you have written, so we can help. By the way, most of the time, [singleton is discouraged.](http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons) – Drogba Apr 29 '13 at 02:33
  • Your `getInstance()` method will be `static` so you cannot override it http://stackoverflow.com/questions/2223386/why-doesnt-java-allow-overriding-of-static-methods - Singletons are not great as scope is comes into play http://stackoverflow.com/a/16076495/573057 – earcam Apr 29 '13 at 02:36
  • @Luiggi, could you add your comment as an answer? You hit the nail first, and none of the current answers come close. – Andy Thomas Apr 29 '13 at 04:12
  • @AndyThomas-Cramer I'm not really sure if that's an answer (yet). Note that OP hasn't added a comment here defending the singleton usage, so I don't think is still proper to post the answer. – Luiggi Mendoza Apr 29 '13 at 04:16
  • @Luiggi - The OP wants to automatically get getInstance() by extending a class. You noted that static methods can't be inherited. – Andy Thomas Apr 29 '13 at 11:55

2 Answers2

11

You cannot extend a proper Singleton since it's supposed to have a private constructor:

Effective Java Item 2: Enforce the singleton property with a private constructor

Evgeniy Dorofeev
  • 124,221
  • 27
  • 187
  • 258
  • 8
    A superclass can be abstract, and a constructor can be protected. – Andy Thomas Apr 29 '13 at 03:26
  • @Andy but than you cannot initiate it. The call to the constructor from getInstance() wouldn't work – Nativ Aug 21 '14 at 08:58
  • @Dalvik - The OP either intends the superclass to be itself a singleton, or not. Presume the former were true. Then the superclass intended to be a singleton could be subclassed, leading to more than one instance, which would make it ... not a singleton. So the former results in a contradiction. The latter is feasible. One could define a superclass for singletons, with a non-private constructor. For this case, the constructor isn't the problem. The problem is `getInstance()`. It needs to be a static method, because it's called without an instance. But static methods aren't inherited. – Andy Thomas Aug 21 '14 at 13:48
  • 1
    @AndyThomas A protected constructor means you can create new instances from anywhere inside the package. That won't be a good singleton now, would it? – rents Aug 13 '15 at 18:14
  • Perhaps, for the sake of argument, in a protected/default/public constructor we can throw an exception in case _INSTANCE is not NULL – rents Aug 13 '15 at 18:18
  • @rents - I haven't suggested creating a non-private constructor for a singleton class. A superclass of a singleton is not necessarily a singleton itself. And this is a good thing, considering that `Object` is a superclass of all Java classes. – Andy Thomas Aug 13 '15 at 18:58
  • Yes, but the question specifically said extending a singleton as well as the answer you commented on. Otherwise you are just stating a fact! – rents Aug 14 '15 at 18:53
3

The only way to override a singleton is to have a singleton that expects to be overridden. The simplest way to do this is to provide Singleton that implements an interface (or is otherwise fully abstract itself) that internally instantiates an injected singleton upon the first use of getInstance().

public interface SingletonMethods // use a better name
{
    String getName();

    void doSomething(Object something);
}

public class Singleton // use a better name
{
    private Singleton() { /* hidden constructor */ }

    public static SingletonMethods getInstance()
    {
        return SingletonContainer.INSTANCE;
    }

    /**
     * Thread safe container for instantiating a singleton without locking.
     */
    private static class SingletonContainer
    {
        public static final SingletonMethods INSTANCE;

        static
        {
            SingletonMethods singleton = null;
            // SPI load the type
            Iterator<SingletonMethods> loader =
                ServiceLoader.load(SingletonMethods.class).iterator();

            // alternatively, you could add priority to the interface, or
            //  load a builder than instantiates the singleton based on
            //  priority (if it's a heavy object)
            // then, you could loop through a bunch of SPI provided types
            //  and find the "highest" priority one
            if (loader.hasNext())
            {
                singleton = loader.next();
            }
            else
            {
                // the standard singleton to use if not overridden
                singleton = new DefaultSingletonMethods();
            }

            // remember singleton
            INSTANCE = singleton;
        }
    }
}
pickypg
  • 20,592
  • 4
  • 65
  • 79
  • Can you write an example for override or extend this Singleton class? – sytolk Feb 23 '17 at 16:11
  • Create a class: `public class SingletonMethodsImpl { public String getName() { return ""; } public void doSomething(Object something) { } }`. Then create a [file for the `ServiceLoader` to use](http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html) in `META-INF/services/package.of.SingletonMethods` whose sole value is `package.of.SingletonMethodsImpl` (where `package.of` is whatever the actual page is). – pickypg Feb 24 '17 at 00:31