【问题标题】:Not inherit some (chosen) methods from derived classes不从派生类继承某些(选择的)方法
【发布时间】:2014-02-01 14:26:11
【问题描述】:

说,例如,我有两个(python(3.3))类a和b,它们有自己的方法:

class a:
    def m1(self):
        print("Hi 1")
    def m2(self):
        print("Hi 2")
        ##...other methods...
class b(a):
    def k1(self):
        print("Other hi")

如何使b 类继承a 的所有方法,除了(例如)m2? (除了复制/粘贴,这不算数。)所以表达式a.m2() 是合法的,但b.m2() 会抛出AttributeError

【问题讨论】:

  • Python 是否允许您定义 b.m2() 以直接抛出该错误?我的意思是说您可以将函数定义覆盖为throw new AttributeError()(或任何适当的语法)...
  • 相反,不从 a 继承 是正确的解决方案。只需根据需要从 a 复制方法即可。

标签: python inheritance


【解决方案1】:

您可以通过将 'a' 和 'b' 兄弟而不是 parent 和 child 来获得所需的效果。这可能对你有用:

class p:
    def m1(self):
        print("Hi 1")

class a(p):
    def m2(self):
        print("Hi 2")

class b(a):
    def k1(self):
        print("Other hi")

所以这些方法现在都是有效的,其他的都会抛出AttributeErrors:

a.m1()
a.m2()
b.m1()
b.k1()

【讨论】:

    【解决方案2】:

    您为什么要这样做?类继承的整个要点是能够测试b 的实例也是a 的实例; isinstance(b(), a)True 出于某种原因。通过从 b 中删除方法,您将严重破坏该模型。

    而是让a 拥有更少的方法,并添加c 以拥有b 不需要的那些:

    class a:
        def m1(self):
            print("Hi 1")
            ##...other methods...
    
    class b(a):
        def k1(self):
            print("Other hi")
    
    class c(a):
        def m2(self):
            print("Hi 2")
    

    或者,您可以不从a 继承,而只需根据需要从a 复制方法:

    class b:
        # copied methods
        m1 = a.m1
    
        def k1(self):
            print("Other hi")
    

    现在b isa a 不再成立,不再期望a 的所有方法都实现了。

    如果a 完全不受您的控制,并且要复制的方法太多,则可以使用__getattr__ 代理并通过m2 以外的任何东西。最后的方法可能是实现m2 并提高AttributeError,但这应该只是最后的手段。

    【讨论】:

    • 会有很多复制的代码,所以我想我会坚持你的第二个选择。谢谢,在冷却期后接受答复。
    • @Thornshadow17432:很高兴能帮上忙!出于好奇;凯文的回答对我来说你接受了他的帖子有什么意义?
    【解决方案3】:

    如果b 继承自a,它应该继承每个方法。那是关于继承的。但如果有必要这样做(注意,不建议这样做),您可以覆盖 m2() 方法,因此它会在调用时引发 Exception

    class b(a):
        def m2(self):
            raise Exception("...")
    

    【讨论】:

      【解决方案4】:

      这并没有真正的意义。继承的重点是使继承对象与基类型完全兼容。这是Liskov substitution principle:只要原始类型的对象可以接受,派生类型的对象也可以接受。

      如果您将派生类型更改为不包含基类型的某些成员,那么您就违反了这一原则。使用 Python 中的动态类型,这不是什么大问题,但它仍然违反了它背后的想法。

      所以你真的不应该那样做。

      【讨论】:

        猜你喜欢
        • 2021-08-14
        • 2014-12-23
        • 2021-12-20
        • 2014-07-09
        • 1970-01-01
        • 2015-01-20
        • 2023-04-09
        • 1970-01-01
        • 2011-01-07
        相关资源
        最近更新 更多