面向对象常用的类的继承却有这种弊端,如何合理地规避呢

继承的好处跟弊端:

  • 继承主要有三个作用:表示is-a关系,支持多态特性(继承后拥有同样的方法),代码复用。虽然继承有诸多作用,但是继承层次过深,过复杂,也会影响代码的可维护性。在这种情况下,我们应该少用,甚至不用继承。实际上,如果继承的层次过深,过于复杂的话,那么就会导致代码的可读性变差。因为我们要搞清楚某个类具有哪些方法、属性、必须阅读父类的代码、父类的父类的代码,一直追溯到最顶层父类的代码。另一方面,继承过深也破坏了类的封装性,将父类的实现细节暴露给了子类。子类的实现依赖父类的实现,两者高度耦合,一旦父类代码修改,就会影响所有子类的逻辑。其实,过于刚刚存在的继承问题,可以利用组合、接口(上篇文章有提过,可以去考考古)、委托三个技术手段来解决。

什么是组合,什么是委托?

  • 通俗易懂的的来说呢,组合指的是一个类变量或者实例变量的定义中使用了其它对象,委托指的是使用上面定义的其它类对象去请求该类对象的方法。

  • 举例说明: 现在有三种动物,狗和鱼和鸡【以下情况都只是举例子而已】,假如说狗会叫和吃东西,鱼会游和吃东西,鸡会下蛋和吃东西,现在希望狗要会游,那么我们可以实现一个狗的类,然后继承了鱼类,那么狗也拥有了鱼的游的能力,又因为两者都会吃,那么可以让鱼继承基本类Base,基本类Base里面是吃的方法,那么此时狗就是一条会吃,会游,会叫的狗了,如果我们还想狗拥有会下蛋的能力,那么可以继承鸡的类,但是这样的多继承甚至多层继承,就会发生上面所说的继承问题,有时候,我们用组合和委托也能达到同样的效果。话不多说,直接上代码

class Base(object):
    def eat(self):
        print('会吃')


class Fish(object):
    def swimming(self):
        print(f'会游泳')


class Chook(object):
    def lag_egg(self):
        print('会下蛋')


class Dog(object):
    def __init__(self):
        self.lag_ability = Chook()  # 【这里是组合】
        self.swimming_ability = Fish()  # 【这里是组合】
        self.eat_ability = Base()

    def lay_egg(self):
        self.lag_ability.lag_egg()  # 这里直接将下蛋这件事委托给鸡类【这里就是委托】

    def swimming(self):
        self.swimming_ability.swimming()  # 这里直接将游泳这件事委托给鱼类【这里就是委托】

    def call(self):
        print('会叫')
    
    def eat(self):
        self.eat_ability.eat()

什么时候用组合和委托,什么时候用继承呢?

  • 总结: 即使没有用继承,上面的狗类也达到了我们要的目的,狗最终也会叫会下蛋会游泳了,因此,确实可以用组合和委托的办法来代替继承。但是凡事都不是绝对的,因为继承改写成组合和委托,意味着要做更细粒度的类的拆分,就要定义更多的类和接口。类和接口的增多或多或少的增加代码的复杂程度和维护成本。所以在实际的开发中,如果类之间的继承结构稳定,继承层次比较浅,比如最多有两层继承关系,继承关系不复杂的话,可以大胆使用继承。反之,系统越不稳定,继承层次很深,关系复杂,尽量使用组合和委托来代替继承。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值