'How to use the second parent class methods which is inheriting from an interface in python?
I am trying to implement an interface and this interface is taken by two concrete classes say class First
and class Second
, I have another class that takes these two classes as a parent class CO
. The class CO
makes a decision based on a flag to return which of the two inherited classes, so as to use their implementation.
from abc import ABC, abstractmethod
class common(ABC):
@abstractmethod
def firstfunction(self):
pass
@abstractmethod
def secondfunction(self):
pass
class First(common):
def __init__(self)-> boto3:
self.ert = "danish"
# self.username = kwargs["username"]
# self.password = kwargs["password"]
print("Inside First function")
def firstfunction(self):
print("My implementation of the first function in FIRST CLASS")
def secondfunction(self):
print("My implementation of the second function in FIRST CLASS")
class Second(common):
def __init__(self):
self.rty = "pop"
# self.session_id = kwargs["session_id"]
print("Inside Second function")
def firstfunction(self):
print("My implementation of the first function in SECOND CLASS")
def secondfunction(self):
print("My implementation of the second function in SECOND CLASS")
class CO(First, Second):
def __init__(self):
self.inst = self.jo()
def jo(self):
a = True
if a:
main_object = First()
return main_object
else:
main_object = Second()
I am instantiating and calling the methods
mymainclass = co()
objt = mymainclass
objt.firstfunction()
objt.secondfunction()
So my condition is if the flag a = True
in the CO
class then the Concrete class First
implementation of the methods should be used and we should get the output like this:
Inside the First function
My implementation of the first function in FIRST CLASS
My implementation of the second function in FIRST CLASS
If the flag a = False
in the CO
class then concrete class Second
should be used and we should get the output like this:
Inside the Second function
My implementation of the first function in FIRST CLASS
My implementation of the second function in FIRST CLASS
From the given code I am getting the following output for the flag a = False
:
Inside the Second function
My implementation of the first function in FIRST CLASS
My implementation of the second function in FIRST CLASS
Can someone make this code work? What am I doing wrong? I know I can make a function that takes these two classes as variables and then return what I want based on a condition. But I want to use classes for the same
Solution 1:[1]
I would not inherit class CO
from either First
or Second
because you want to end up with an object that is either an instance of class First
or class Second
. The most straightforward way of doing this is to define method __new__
which will give you more control over instance creation.
Keep all of your code the same (after fixing the obvious errors, such as boto3
not being defined) and changing class CO
as follows:
class CO:
def __new__(cls):
a = True
if a:
main_object = First()
else:
main_object = Second()
return main_object
o = CO()
print(type(o))
Prints:
Inside First function
<class '__main__.First'>
If you want to better parameterize the instance creation (and simplify the code within __new__
), then have variable a
be an argument to CO
:
class CO:
def __new__(cls, a):
return First() if a else Second()
o = CO(False)
print(type(o))
Prints:
Inside Second function
<class '__main__.Second'>
You could optionally have class CO
have common
as its base class to document that instantiating this class results in an instance that implements the common
interface. But doing so will not result in enforcing the actual type that is returned by __new__
:
class CO(common):
def __new__(cls, a) -> common:
# The Python interpreter is not type-checking what is returned:
#return First() if a else Second()
return []
o = CO(False)
print(type(o))
Prints:
<class 'list'>
You can also substitute a factory function for class CO
:
def common_factory(a):
return First() if a else Second()
o = common_factory(False)
Note
If you want to ensure that classes that inherit from base class common
must override both firstfunction
and secondfunction
to more closely emulate a pure interface as implemented in other object-oriented languages, then you should define these functions in common
so that they raise an NotImplementedError
exception:
class common(ABC):
@abstractmethod
def firstfunction(self):
raise NotImplementedError
@abstractmethod
def secondfunction(self):
raise NotImplementedError
Unfortunately, the enforcement is done at run time with its attendant surprises instead of at compile time as is done in other object-oriented languages.
Solution 2:[2]
Okay I think in this situation, CO class must come from common class and implement the first and second function. In the implementation, it will use the First or Second classes functions depends on the result of jo function. Here is the correct Co class code:
class CO(common):
def __init__(self):
self.inst = self.jo()
def jo(self):
a = False
if a:
return First()
return Second()
def firstfunction(self):
self.inst.firstfunction()
def secondfunction(self):
self.inst.secondfunction()
a = CO()
a.firstfunction()
a.secondfunction()
Solution 3:[3]
You can directly call the method you want by using the class name.
Unless you have some pressing reason to do this that you didn't include in your question, I would avoid this in favor of a factory function that returns either a First
or Second
instance depending on the inputs.
class common(ABC):
@abstractmethod
def firstfunction(self):
pass
@abstractmethod
def secondfunction(self):
pass
class First(common):
def __init__(self):
self.ert = "danish"
super().__init__(self)
def firstfunction(self):
print("My implementation of the first function in FIRST CLASS")
def secondfunction(self):
print("My implementation of the second function in FIRST CLASS")
class Second(common):
def __init__(self):
self.rty = "pop"
super().__init__(self)
def firstfunction(self):
print("My implementation of the first function in SECOND CLASS")
def secondfunction(self):
print("My implementation of the second function in SECOND CLASS")
class CO(First, Second):
def __init__(self):
super().__init__(self)
def use_first(self):
return True or False # whatever logic you have for determining this
def firstfunction(self):
if self.use_first():
return First.firstfunction(self)
else:
return First.firstfunction(self)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Muhammet Nusret Özate? |
Solution 3 | Patrick Haugh |