views:

510

answers:

8

Today I faced one question in interview. Is it possible to apply inheritance concept on Singleton Classes? I said since the constructor is private, we cannot extend that Singleton class.

Next thing he asked me is to apply inheritance on that Singleton class. So, I made the Singleton's constructor as protected thinking that child's constructor also has be protected. But I was wrong the child can have a modifier either equal to or higher than that.

So, I asked him to give a real world example on such a case. He was not able to give me one and said that I cant ask questions and wanted me to tell whether this scenario is possible or not.

I went kind of blank. My question here is,

  • Is this possible?
  • Even if it is possible, what is the use of it?
  • What real world scenario would demand such a use?
+3  A: 

Its 'possible' to hack anything together really, but in this case it is not really advisable. There's no real reason to use the singleton pattern with inheritance, its just not meant for it.

Paul
+1: I guess it's a good reason that the Enum class can't be extended.
Espen
Actually, the pattern was very much and explicitly meant for inheritancy by the people who invented it.
Michael Borgwardt
+4  A: 

You can create an abstract base class with a bunch of common attributes and methods, and then create a number of subclasses as singleton classes. That is "applying the inheritance concept" ... in a useful way.

But what you cannot do is create a subclass of a strictly implemented singleton class. If you declare the singleton classes constructor as private a subclass won't compile. If you declare it with some other access, the constructor could be used in another class to create multiple instances ... ergo it is not strictly a singleton. If you declare the singleton as abstract, it cannot be instantiated at all ... ergo it is not a singleton.

Stephen C
Hmm.. Assume I am the interviewer and I ask you to deliver me a singleton that is extendable. (Believe me this is how he was asking the same question again and again). What would you do.
Bragboy
@Bragaadeesh - see my second paragraph above + my comment about reflection not working. Either he was trying to make some subtle point about the difference between design and implementation, or he was just plain ignorant. If he didn't accept the earlier explanations, my final answer would be a polite *"I believe that it is impossible ... can we move onto the next question please"*.
Stephen C
@Bragaadeesh - another possibility was that the interviewer was just seeing how you might handle an impossible problem ... or a difficult coworker.
Stephen C
@Stephen: But according to quotes from Michael (the selected answer), it seems that we are ignorant.
Bragboy
@Bragaadeesh -- but seem my comments on Michael's answer about singleton class versus singleton pattern. See also my comment above. If the interviewer was claiming that (for example) the "registry" approach gives true singleton classes, I claim he is wrong. But either way, he is splitting hairs and this is about as useful in an interview as arguing whether vi or emacs is better ...
Stephen C
+6  A: 

Yes, it is technically possible, as singleton is a design pattern and not a language construct that could have inheritance restrictions. I would just reimplement the public [Object] getInstance() method in the child classes (see below).

And, yes, singletons can also benefit from inheritance as they may share similar but not identifical behaviours with other singletons.

public class ParentSingleton {

    private static ParentSingleton instance;

    protected ParentSingleton() {
    }

    public static synchronized ParentSingleton getInstance() {
       if (instance == null) {
          instance = new ParentSingleton();
       }

       return instance;
    }

    public int a() {
       // (..)
    }       
}

public class ChildSingleton extends ParentSingleton {

    private static ChildSingleton instance;

    public static synchronized ParentSingleton getInstance() {
       if (instance == null) {
          instance = new ChildSingleton();
       }

       return instance;
    }       
}

EDIT: as Eyal pointed out in his comments below, the constructor in the super class had to be made protected (instead of private), otherwise it would not be visible to the child classes and the code would not even compile.

Bruno Rothgiesser
In that case you could not have extended the class in the first place..
Bragboy
"Other singletons" is an oxymoron. If they're all extending the same (singleton) base class, there should only ever be one of them.
cHao
The code does not compile. The instance member is not static, and you have no visible super constructor to use.
Eyal Schneider
@Eyal - thanks, fixed
Bruno Rothgiesser
@Bruno: But now your singleton does not follow the strict design pattern, since the constructor is protected.
Eyal Schneider
Need to make your getInstance() methods `synchronized` to be thread-safe.
David Gelhar
@Eyal - I agree, but the general purpose of the design pattern is still preserved.
Bruno Rothgiesser
@David, added, thanks
Bruno Rothgiesser
@Eyal: a protected constructor *is* the strict design pattern - look it up.
Michael Borgwardt
@Michael: Looks like you are right. It increases the risk of multiple-copies, but the risk exists anyway (reflection/serialization etc) so the reusability benefit dominates.
Eyal Schneider
@Bruno Rothgiesser will not calling ParentSingleto::getInstance() and ChildSingleton ::getInstance() creates two instances of the singleton object ParentSingleton
yesraaj
@yesraaj - yes and no :-) `ChildSingleton.getInstance()` will return an instance of `ChildSingleton`, because the instance is created with `new ChildSingleton()`. But it's also correct to say that this method returns an instance of `ParentSingleton`, since `ChildSingleton` extends that class, i.e. `ChildSingleton` is a `ParentSingleton`.
Bruno Rothgiesser
@Bruno so now u have 2 objects of singleton class `ParentSingleton`
yesraaj
@yesraaj - Yes, because `ChildSingleton` is a `ParentSingleton` too. Think of a class Apple that extends Fruit. Instances of Apple are also instances of Fruit.
Bruno Rothgiesser
@Bruno Rothgiesser Is not singleton doesn't have more one objects :)
yesraaj
@yesraaj - I see your point. But I'm not really advocating in favour of this practice. I posted the code that I would have written in an interview had the interviewer asked me to implement that. Maybe the interviewer was actually expecting us to answer that "it's not possible"... who knows?
Bruno Rothgiesser
@Bruno Rothgiesser I have answered the question based on the explanation provided in gang og four book. Have a look at the answer provided below, but the answer is in c++.
yesraaj
A: 

You could make the constructor package-private. This way, no classes outside the package could instantiate the Singleton class but derived classes could call the upper class constructor.

But, as others said, this is really not advisable.

Stupid interview question by the way.

Helper Method
+1  A: 

I'm guessing this isn't what he wasn't looking for, but if you want to get technical you could also mention that Singleton is a pattern, not an implementation. Messing with the class constructor isn't the only way to have a Singleton, you could have a factory enforcing the pattern, in which case you can use inheritance in exactly the same way as with other classes.

Manos Dilaverakis
+7  A: 

Citing the bible:

Use the Singleton pattern when [...] the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code.

The Singleton pattern has several benefits: [...] 3. Permits refinement of operations and representation. The Singleton class may be subclassed, and it's easy to configure an application with an instance of this extended class. You can configure the application with an instance of the class you need at run-time.

As for how to implement this: the book suggests several way, the most sophisticated of which is a registry in which instances are looked up by name.

Michael Borgwardt
From where you got the points inside the quotes. I cannot find it on the link you've given.
Bragboy
+1, finally a sensible answer. Obviously a lot of people fail to realize that while there must never be more than one instance of the singleton at runtime, the type of that one instance could be configurable!
Jonas H
@Bragaadeesh: the text is from the content of the book that the Wikipedia article is about. It's *the* book about design patterns, which pretty much invented the term (as applied to software) and most of the widely-known pattern names.
Michael Borgwardt
This is not a singleton class. It is an implementation of the singleton pattern. For example, the registry approach only gives singleton behaviour if programmers obey the rules. If they don't obey the rule that instances must only be obtained from the registry, the pattern breaks. This is what other answers/comments meant when they talked about the distinction between the singleton design pattern and a singleton class.
Stephen C
+2  A: 

Below is one implementation of singleton pattern explained in GOF about creating singleton with inheritance. Here the parent class should be modified to add a new derived class. Environment variable can be used to instantiate appropriate derived class constructor.

Mainfile – 1
#include <iostream>
#include <string>
#include "Singleton.h"
using namespace std;

int main(){

     Singleton::instant().print();
     cin.get();
}
Singleton.h
#pragma once
#include <iostream>
using std::cout;
class Singleton{
public:
    static Singleton & instant();
    virtual void print(){cout<<"Singleton";}
protected:
    Singleton(){};
private:
    static Singleton * instance_;
    Singleton(const Singleton & );
    void operator=(const Singleton & );

};

Singleton.cpp
#include "Singleton.h"
#include "Dotted.h"
Singleton * Singleton::instance_ = 0;
Singleton & Singleton::instant(){
    if (!instance_)
    {
        char * style = getenv("STYLE");
        if (style){
            if (strcmp(style,"dotted")==0)
            {
                instance_ = new Dotted();
                return *instance_; 
            }           else{
                instance_ = new Singleton();
                return *instance_;
            }       
        }

        else{
            instance_ = new Singleton();
            return *instance_;
        }
    }
    return *instance_;

}
Dotted.h

#pragma once
class Dotted;

class Dotted:public Singleton{
public:
    friend class Singleton;
    void print(){cout<<"Dotted";}
    private:
        Dotted(){};

};
yesraaj
+1 this is interesting, thanks
Bruno Rothgiesser
Indeed it is...
Bragboy
@Bragaadeesh Just wanted you to have a look in case you have missed :)
yesraaj
@Yesraaj. Ofcourse I wont After all its 'my' question :)
Bragboy
+2  A: 

A private constructor is visible to other inner classes of that singleton class. So yes, technically a singleton class with a private constructor can be extended by its inner class. But why would you do something like that is beyond me.

Ashish