代码之家  ›  专栏  ›  技术社区  ›  Mark van der Wilk

用于重写继承方法的Mixin

  •  5
  • Mark van der Wilk  · 技术社区  · 8 年前

    我有一组类,A1、A2、A3等,它们都有方法 m() .我也有B类方法 m() 我希望能够轻松地创建类C1、C2、C3等,这些类调用 m() 同时还具有A1、A2、A3等所有其他性质。。。

    然而,我遇到的问题是,在类C1中,方法 m() B班的学生应该打电话 m() 来自类别A1。

    我很难用语言表达我想要的东西,但我目前考虑的方式是使用mixin。C1将继承A1,混合B。然而,我不知道如何制作 m() 在B中调用正确的 m() 来自一个A类。

    所以,我的两个问题:

    • 我想做的事情有名字吗?
    • 正确的做法是什么?

    编辑:根据要求,具体示例: 方法 m(p) 在A1、A2、A3等中都计算矩阵 M ,对于某些参数 p 我想创建类C1、C2、C3等,它们的行为方式与A1、A2、A3、…相同, 除了 对于方法 m() .新方法 m() 需要更长的参数列表 p ,大小为N,我们计算 A*.m() N次,然后返回总和。

    用于计算 m() 对于所有A*类都是相同的。在上述建议的混合解决方案中,求和代码将在B中。B和A1都将被继承以形成C1。然而,该方法 m() 在里面 C1 B必须打电话 A1.m() .

    1 回复  |  直到 8 年前
        1
  •  7
  •   MSeifert    8 年前

    我想你只需要 super 它将调用重定向到父类或兄弟类(取决于MRO)。

    例如:

    class A1(object):
        def m(self):
            print('Calling method m of class A1')
            self.data *= 2
    
    class A2(object):
        def m(self):
            print('Calling method m of class A2')
            self.data *= 3
    
    class A3(object):
        def m(self):
            print('Calling method m of class A3')
            self.data *= 4
    
    class B(object):
        def m(self, p):
            print('Calling method m of class B')
            for i in range(p):
                # You haven't specified which python you are using so I assume
                # you might need to most explicit variant of super().
                # Python3 also allows just using super().m()
                super(B, self).m()
    
    class C1(B, A1):
        def __init__(self, value):
            self.data = value
    

    只是测试一下:

    a = C1(10)
    a.m(10)
    

    打印:

    Calling method m of class B
    Calling method m of class A1
    Calling method m of class A1
    Calling method m of class A1
    Calling method m of class A1
    Calling method m of class A1
    Calling method m of class A1
    Calling method m of class A1
    Calling method m of class A1
    Calling method m of class A1
    Calling method m of class A1
    

    以及保存的值:

    a.data
    # returns 10485760
    

    定义其他 C 同样有效:

    class C2(B, A2):
        def __init__(self, value):
            self.data = value
    
    a = C2(10).m(2)
    #Calling method m of class B
    #Calling method m of class A2
    #Calling method m of class A2
    
    
    class C3(B, A3):
        def __init__(self, value):
            self.data = value
    
    a = C3(10).m(1)
    #Calling method m of class B
    #Calling method m of class A3
    

    当然,您需要另一个逻辑,可能需要从 .m() 而不是就地修改,但我认为你可以自己解决。

    你要找的词可能是 MRO (method resolution order) 。希望这对你有帮助。

    同样感兴趣的还有 super (Python2) , super (Python3) .

    你可以随时查看 MRO 通过调用 .mro() 方法:

    print(C1.mro())
    [<class '__main__.C1'>, <class '__main__.B'>, <class '__main__.A1'>, <class 'object'>]
    

    所以python首先检查 C1 有一个方法 m 如果没有检查 B . B 有一个,所以它被执行。这个 超级的 呼叫然后再次进入 MRO公司 并检查下一节课( A1 )有一个方法 ,然后执行。