tags:

views:

378

answers:

6

I am sorry if this is a duplicate or too elementary, but how do I make a singleton class that can be subclassed?

+5  A: 

You generally can't, in any useful sense. This would be yet another reason to not use Singleton classes.

Mark Bessey
+1  A: 

If you have defined your singleton as:

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

Then you can just do:

public class NewSingleton extends Singleton {
}

But, you won't be able to use the private methods so if you want to use the singleton you will still need to call Singleton.getInstance(); so you gain nothing by extending it.

But, there is no reason why you can't do it.

Now, if you want to add more functions to the Singleton class then you can use inter-type aspects from AspectJ and just inject new methods/properties into the Singleton which could then be used by the Singleton.

James Black
+1  A: 

Singleton limits instances not the inheritance. Well - as already been pointed out it limits usefulness of inheritance and then you can relax private constructor to packaged or protected (which you may argue diminishes singletoness of the singleton) But what is the purpose?

DroidIn.net
+2  A: 

Actually, I don't think it is possible.

You make a class singleton by declaring its constructor(s) to be private. But if you then try to declare a subclass of your singleton class, the subclasses constructor wont be able to see the constructors of the superclass ... so they won't compile; e.g.

public class A () {
    private A() { }
}

public class B () {
    private B() { }
}

Both the Sun JDK 1.6 and Eclipse Ganymede compiler give a compilation error in the constructor B, to the effect that the no-args constructor for A is not visible.

You could increase the visibility of the private constructors, but then there is nothing (apart from good sense) stopping someone from creating multiple instances of it. In other words it is not really a singleton class anymore.

EDIT: I guess a kosher alternative would be to define a tree of one or more abstract (non-singleton) classes with the methods / members that you want to be common, and then define multiple singleton classes as a leaf classes as appropriate. But that is NOT one singleton class subclassing another one.

Stephen C
It compiles... I'm idiot enough to waist my time on creating 2 test classes. So it does (at least - no argument constructors)
DroidIn.net
Oh bullocks - 'waste' that is
DroidIn.net
What do cattle have to do with this ??? :-)
Stephen C
It doesn't compile for me. The (eclipse) compiler says "Implicit super constructor A() is not visible. Must explicitly invoke another constructor." This is in the constructor for class B where B extends A, and both A and B have explicit private no-args constructors.
Stephen C
+8  A: 

Steve Yegge has an amusing article about singletons that mentions subclassing in this quote:

Then there's the subclassing thing. It's almost impossible to subclass a Singleton, and if you manage it, then you shouldn't have been using a Singleton in the first place. You don't even want to go there. I've walked roads that I dare not recount. Just pretend you can't do it, and you'll save yourself amazing amounts of pain.

Chris Farmer
So the answer is "NO"?
kunjaan
If you want to read it that way, then yes, it's no. Or you could read it and see that the answer is yes, but you still shouldn't try it, and you might want to evaluate why you're using a singleton in the first place.
Chris Farmer
A: 

As others have replied already, the uses of singleton subclassing are small. If you need a strategy pattern in the context of a singleton, you could define an interface and delegate to an implementation of that interface in the singleton instance. This moves the problem one layer down and makes it more clear why you would want to do it.

To answer your question; assuming the choice for the particular subclass your application uses is defined in for instance the system properties, you can do something like:

public static synchronised Singleton getInstance() {
    if (instance == null) {
        String clsName = System.getProperties().getProperty("singleton.class");
        if (className == null || 0 == clasName.length()) {
            instance = new Singleton();
        } else {
            Class cls = Class.forName(clsName);
            instance = (Singleton) cls.newInstance();
        }
     }
     return instance;
}

Disclaimer: untested code, add exception handling, etc :-) Btw, make sure your getInstance() method is synchronised.

rsp