Reputation: 71
My concern is related to one question posted here, but this time referred to Python language rather than C#.
I am aiming to use the same class to instantiate (two) different objects which share some methods, but not all of them. I came to the conclussion that the most efficient way to do so, if existing, might be to add an attribute which could give access to one or another set of methods depending on its value, while sharing the ones that are used for both cases. Is this actually possible in Python? If not, how would you recommend me to deal with this issue?
Thank you in advance, and best regards.
EDIT #1: I actually have one more small question regarding the use of Factory in this context, related to the use of more arguments and functions shared by the rest of the subclasses. Would this be the right way of defining my problem? Can 'init' and 'sharedFunction' methods be defined separate from the 'factory' one?
class Object:
def __init__(self, serial, np, t):
self.serial = serial
self.np = np
self.t = t
# Factory method
def factory(model):
if model == 'modelA':
return ModelA()
if model == 'modelB':
return ModelB()
# Shared function
def sharedFunction(self):
pass
class ModelA(Object):
def function1(self):
self.t.sleep(10)
So that later we can instantiate and use the objects as:
>>> modelA = Object.factory('modelA')
>>> modelA.function1()
Thanks a lot for your time.
EDIT #2 (after comment #9): There is still one thing which is not clear enough for me, concerning the definition of attributes within the superclass factory function. Is it mandatory to initialize with specific values or doing so just with the ones provided by the constructor (which is would make sense to me) would do the trick?
class Object(object):
def __init__(self, serial, np, t):
self.serial = serial
self.np = np
self.t = t
# Factory method
@staticmethod
def factory(model):
if model == 'modelA':
return ModelA(serial, np, t) # Here is where I am given an error message. Must I initialize the attributes of modelA and modelB with specific values? Why can't I do so for instance either with self.serial or just serial as I just created the constructor above?
if model == 'modelB':
return ModelB(serial, np, t) # Same as above
# Shared function
def sharedFunction(self):
pass
class ModelA(Object):
def __init__(self, serial, np, t, other_stuff):
super(ModelA,self).__init__(serial, np, t)
self.other_stuff = other_stuff
def function1(self):
self.t.sleep(10)
So that later we can instantiate and use the objects as:
>>> modelA = Object.factory('modelA', other_stuff)
>>> modelA.function1()
Upvotes: 1
Views: 1386
Reputation: 657
What you are describing sounds very much like a factory. In its simplest form, it can be implemented in the following way:
class Animal:
@staticmethod
def factory(kind):
if kind == 'Cat':
return Cat()
elif kind == 'Bird':
return Bird()
class Cat(Animal):
def say(self):
return 'Meow'
class Bird(Animal):
def say(self):
return 'Chirp'
Now you can instantiate Animal
s using the factory()
method which will automatically pick a subclass based on the kind
parameter:
>>> bird = Animal.factory('Bird')
>>> bird.say()
'Chirp'
EDIT:
It is possible to define other methods in the base class, such as __init__()
or sharedFunction()
. However, to make the parent-class attributes (self.serial
etc.) accessible to the subclass, the parent class constructor has to be called. This can be accomplished in two ways:
Override the constructor in subclasses and call the parent class constructor from it:
class ModelA(Object):
def __init__(self, serial, np, t, other_stuff):
# Note: in Python 2, this requires `Object` to inherit from `object`
super(ModelA, self).__init__(serial, np, t)
self.other_stuff = other_stuff
In both cases, you have to pass the relevant arguments to the constructor when creating the object in factory()
. In (1), this means you have to do something like:
if model == 'modelA':
return ModelA(serial=42, np='p', t=0)
In (2), you have to provide any extra parameters you added:
if model == 'modelA':
return ModelA(serial=42, np='p', t=0, other_stuff='something')
Also not that factory()
has to be defined as @staticmethod
in order to make it callable without a specific instance.
Upvotes: 1