在Python中,无需继承父类即可更改继承的行为

时间:2019-05-07 20:02:26

标签: python class oop inheritance

在Python中,我有一个ParentClass类。它定义了方法ParentClass.process()等。 ParentClass由两个子类继承:ChildA和ChildB。这是系统的一部分,像拨轮一样。用户应该不能更改软件包的代码。

在执行过程中,系统创建ChildA和ChildB的对象。

现在,我想让系统用户能够更改ChildA和ChildB对象的.process()方法的行为。

很明显,她可以通过重新定义ChildA.process()和ChildB.process()来做到这一点,但这将两次复制相同的行为,并且总体看来是很奇怪的方法。

用户可以从ParentClass继承她自己的类并在那里重新定义.process(),但这意味着我需要以某种方式动态地告诉ChildA和ChildB继承什么。

此外,除了.process()之外,所有类(ParentClass,ChildA和ChildB)都具有其他方法,这些方法无需更改即可保留。

请帮助我找出最方便用户的方式(也许也是最“ pythonic”的方式)。

2 个答案:

答案 0 :(得分:1)

您可以使用类方法为特定的类重新分配process

class ParentClass:
    def process(self):
        print("parent")
    @classmethod
    def reassign_process(cls, process):
        cls.process = process

class ChildA(ParentClass):
    def process(self):
        print("Child A")

class ChildB(ParentClass):
    def process(self):
        super().process()
        print("Child B")

p = ParentClass()
ca = ChildA()
cb = ChildB()

p.process()
# parent
ca.process()
# Child A
cb.process()
# parent
# Child B

def new_parent_process(self):
    print("New parent")

ParentClass.reassign_process(new_parent_process)

def new_childa_process(self):
    print("New child A")

ChildA.reassign_process(new_childa_process)

p.process()
# New parent
ca.process()
# New child A
cb.process()
# New parent
# Child B

答案 1 :(得分:1)

您可以使用中间继承将通用替代定义为基类的扩展:

class ParentClass:
    def process(self):
        print("ParentClass.process() called from",type(self))

class ExtendedParent(ParentClass): 
    def process(self):
        super().process()
        print("Common Extension code for A and B",type(self))

class ChildA(ExtendedParent):
    pass

class ChildB(ExtendedParent):
    pass

a = ChildA()
b = ChildB()

a.process()
# ParentClass.process() called from <class '__main__.ChildA'>
# Common Extension code for A and B <class '__main__.ChildA'>

b.process()
# ParentClass.process() called from <class '__main__.ChildB'>
# Common Extension code for A and B <class '__main__.ChildB'>

如果在包中定义了ChildA和ChildB并且没有.process()方法,则可以指示包的用户使用不属于任何类的通用函数直接将方法分配给这些类:

def extendedProcess(self):
    ParentClass.process(self) # this replaces super().process()
    print("Common Extension code for A and B",type(self))

ChildA.process = extendedProcess        
ChildB.process = extendedProcess

如果ChildA和/或ChildB具有对process()的覆盖,并且您的用户想要更改父类中process()的行为,则可以采用以下一种方法:

ParentClass_process = ParentClass.process
def extendedProcess(self):
    ParentClass_process(self) #call original code
    print("Common Extension code for A and B",type(self))    
ParentClass.process = extendedProcess