1. 程式人生 > >面向對象之多繼承

面向對象之多繼承

多繼承

多繼承

  • Python不同版本的類

    Python2.2之前類是沒有共同的祖先的,之後引入object類,它稱為新式類.
    Python2中為了兼容,分為舊式類(古典類)和新式類
    Python3中全部都是新式類
    新式類都是繼承自object的,新式類可以使用super.
  • 多繼承

    OCP原則: 多繼承、少修改
    繼承的用途: 增強基類、實現多態

    多態
    在面向對象中,父類、子類通過繼承聯系在一起,如果通過同一個方法,實現了不同的表
    現,就是多態.就相與不同的實例使用同一方法,得到的結果不同.

    一個類繼承自多個類就是多繼承,它具備多個類的特征
  • 多繼承的優缺點


    優點:
        多繼承能更好的模擬現實世界
    缺點:
        多繼承舍棄簡單,引入復雜性,帶來沖突

    示例:
        一個孩子繼承父母雙方的特征.那麽他的眼睛是像爸爸還是媽媽呢?像誰的多一點
        呢?

    多繼承的實現會導致編譯器設計的復雜度增加,所以現在很多語言也舍棄了類的多繼承
    C++支持多繼承;Java舍棄了多繼承
    Java中,一個類可以實現多個接口,一個接口也可以繼承多個接口.Java的接口很純粹,
    只是方法的聲明,而讓繼承者來實現這些方法,於是具備了這些能力

    多繼承可能會帶來二義性,例如,一個類繼承自貓和狗,貓和狗都有shout方法,那麽子類
    是繼承誰的shout方法呢?

    解決方案:
        實現多繼承的語言,需要解決二義性,即繼承的規範,是深度優先還是廣度優先
  • Python多繼承實現


語法:

class 類名(基類列表):

語句塊

Python使用MRO(method resolusion order)解決基類搜索順序問題



需求: 為Document子類提供打印功能

思路:

1 在基類中提供print方法

基類提供的方法不應該具體實現,因為它未必適合子類的打印,子類中需要覆蓋重

寫,而且print算是一種能力–打印能力,不是所有的Document子類都需要.

2 在需要打印功能的子類上添加

如果直接在子類上增加,則違反了OCP原則,所以應該繼承後添加


# 第一種思路實現
class Document: 
    def printable(self):
        print(‘Document‘)

class Word(Document):
    def printable(self):
        print(‘word‘)

class Pdf(Document): pass

Word().printable()
Pdf().printable()
# 第二種思路實現
class PrintableWord(Word):
    @classmethod
    def print(cls):        # print = classmethod(print)
        print(id(print))
        print(‘printword‘)

class Document: 
    def printable(self):
        print(‘Document‘)

class Word(Document): pass
class Pdf(Document): pass

PrintableWord().print()
print(PrintableWord.__dict__)
print(PrintableWord.__mro__)
第二種思路的缺陷在在於,如果需要更多功能的實現,有些類需要,而有些類不需要,
使用此方法,則會寫很多類.
解決方案: 
    1. 可以使用裝飾器,寫一個功能就給一個類添加一個功能,不用此功能就取消裝飾器,
    增添功能非常靈活
    2. 使用Mixin,多繼承的思路,寫一個類,有需要添加的功能,在將此類和需要功能的類
    組合在一起,也能解決此問題,並且類還可以繼承


# 裝飾器實現
# 裝飾器函數,給類添加打印功能的屬性
def printable(cls):
    cls.printable = lambda self: print(self.content)
    return cls

class Document: 
    def __init__(self,content):
        self.content = content

class Word(Document): pass
class Pdf(Document): pass
@printable
class PrintableWord(Word): pass

PrintableWord(‘word print‘).printable()
print(PrintableWord.__dict__)
print(PrintableWord.__mro__)


# Mixin實現
# Mixin實現附加打印功能

class Document: 
    def __init__(self,content):
        self.content = content

class Word(Document): pass
class Pdf(Document): pass

class PrintableMixin:
    def print(self):
        print(self.content,‘ Mixin‘)
class PrintableWord(PrintableMixin,Word): pass
PrintableWord(‘word print‘).print()
print(PrintableWord.__mro__)

# 通過繼承Mixin,實現加強Mixin的打印功能
class SuperPrintableMixin(PrintableMixin):
    def print(self):
        print(‘strengthen‘)
        super().print()
        print(‘strengthen‘)
class PrintableWord(SuperPrintableMixin,Word): pass
PrintableWord(‘word print‘).print()
print(PrintableWord.__mro__)


  • Mixin類

Mixin本質上就是多繼承的實現
Mixin體現的是一種組合的設計模式
在面向對象的設計中,一個復雜的類,往往需要很多功能,而這些功能都來自不同的類,
這就需要很多類組合在一起.
從設計模式的角度來說,多組合、少繼承

Mixin類的使用原則
1 Mixin類中不應該顯示的出現__init__初始化方法
2 Mixin類通常不能獨立工作,因為它的作用是混入別的類中來實現部分功能
3 Mixin類的祖先類也應該是Mixin類

使用時,Mixin類通常在繼承列表的第一個位置
例如class PrintableWord(PrintableWord,word):pass

組合的實現可以使用裝飾器或Mixin,如果要使用繼承的話,使用Mixin.


本文出自 “12064120” 博客,請務必保留此出處http://12074120.blog.51cto.com/12064120/1981086

面向對象之多繼承