Reputation: 59
My idea is any one of the objects should exist for all the subclasses of a Singleton class. The code that I have been trying and the result matrix is given below. The matrix seems to be working fine in the case of subclasses. Am I going the wrong way? Did it get what happens in the case of a Parent class object and a subclass object?
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(
cls, *args, **kwargs)
return cls._instance
class A(Singleton):
def __new__(cls, *args, **kwargs):
super(A, cls).__new__(cls, *args, **kwargs)
class B(Singleton):
def __new__(cls, *args, **kwargs):
super(B, cls).__new__(cls, *args, **kwargs)
class C(B):
def __new__(cls, *args, **kwargs):
super(B, cls).__new__(cls, *args, **kwargs)
if __name__ == '__main__':
s1=Singleton()
s2=Singleton()
if(id(s1)==id(s2)):
print "Same"
else:
print "Different"
'''
I got a result matrix for s1 and s2
|************ s2 **************************|
s1 |Singleton() |A() | B() | C() |
===========|==========================================|
Singleton()|Same |Different|Different|Different|
A() |Different |Same |Same |Same |
B() |Different |Same |Same |Same |
C() |Different |Same |Same |Same |
'''
Upvotes: 5
Views: 12456
Reputation: 34334
None of the subclasses' __new__()
methods have an explicit return
statement, so they all return None
. That's why their new instances are all the same. With this code, they'll be the same as Singleton()
too:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
class A(Singleton):
def __new__(cls, *args, **kwargs):
return super(A, cls).__new__(cls, *args, **kwargs)
class B(Singleton):
def __new__(cls, *args, **kwargs):
return super(B, cls).__new__(cls, *args, **kwargs)
class C(B):
def __new__(cls, *args, **kwargs):
return super(C, cls).__new__(cls, *args, **kwargs)
It's not even necessary to define __new__()
for the subclasses:
class A(Singleton):
pass
class B(Singleton):
pass
class C(B):
pass
Upvotes: 5
Reputation: 491
I solve this problem with help of abstract classes. In my it looks like:
from abc import ABCMeta, abstractmethod
class BasicClass(object):
__metaclass__ = ABCMeta
instance = None
def __new__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = super(BasicClass, cls).__new__(
cls, *args, **kwargs)
return cls.instance
@abstractmethod
def action(self):
pass#do smthing
class FirstLevelChild(BasicClass):
__metaclass__ = ABCMeta
@abstractmethod
def action(self):
pass#do smthing in this or other abstract method
# also pearent method can be called with help of super
class SecondLevelChild1(FirstLevelChild):
def action(self):
pass#do smthing unique for this class
# in this or other abstract method
# also pearent method can be called with help of super
class SecondLevelChild2(FirstLevelChild):
def action(self):
pass#do smthing unique for this class
# in this or other abstract method
# also pearent method can be called with help of super
Lets check
>>> a1 = SecondLevelChild1()
>>> a2 = SecondLevelChild1()
>>> b1 = SecondLevelChild2()
>>> b2 = SecondLevelChild2()
>>> a1 == b1
False
>>> a1 ==a2
True
>>> b1 == b2
True
>>>
ATTENTION! This solution will help if You need to instantiate only last level child classes. You would not able to instantiate abstract classes.
Upvotes: 0
Reputation: 226336
The code looks fine but it doesn't make sense to pick one singleton value to be shared for a class and its subclasses. The whole point of a subclass is to be different in some way from the parent class and from sibling subclasses. It seems odd to me that each class doesn't have its own distinct singleton instance.
Upvotes: 4