python面向對象中的封裝、繼承、多態

封裝

能夠簡單的理解爲隱藏一切能夠隱藏的實現細節,只向外界提供簡單的編程接口。咱們在類中定義的方法其實就是把數據和數據的操做封裝起來了,在咱們建立了對象以後,只須要給對象發送一個消息(調用方法)就能夠執行方法中的代碼,也就是說咱們只須要知道方法的名字和傳入的參數(方法的外部視圖),而不須要知道方法內部的實現細節(方法的內部視圖)。java

練習:定義一個類實現一個數字數種python

import time


class Clock:

    def __init__(self):
        # 獲取當前系統時間
        t = time.localtime()
        self._hour = t.tm_hour
        self._minute = t.tm_min
        self._second = t.tm_sec

    def run(self):
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute += 1
            if self._minute == 60:
                self._minute = 0
                self._hour += 1
                if self._hour == 24:
                    self._hour = 0

    def show(self):
        return "%02d:%02d:%02d" % (self._hour, self._minute, self._second)


def main():
    clock = Clock()
    while True:
        # 將光標退到當前行首
        print("\r%s" % clock.show(), end="")
        time.sleep(1)
        clock.run()


if __name__ == '__main__':
    main()

繼承

在現實生活中,繼承通常指的是子女繼承父輩的財產,以下圖 編程

搞很差,結果以下.. spa

在程序中繼承是描述事物之間的所屬關係,例如貓和狗都屬於動物,程序中即可以描述爲貓和狗繼承自動物;同理,波斯貓和巴釐貓都繼承自貓,而沙皮狗和斑點狗都繼承自狗,以下如所示: code

子類能夠繼承父類的公共屬性和公共方法,父類中私有的屬性和方法不能被繼承。對象

單繼承

通常只繼承一個父類就叫作單繼承,在java等靜態語言中只能繼承一個父類,也就不存在單繼承和多繼承了。 示例代碼:blog

# 定義一個父類,以下:
class Cat(object):

    def __init__(self, name, color="白色"):
        self.name = name
        self.color = color

    def run(self):
        print("%s--在跑"%self.name)


# 定義一個子類,繼承Cat類以下:
class Bosi(Cat):
	# 子類沒有實現__init__方法,則自動調用父類的__init__方法

    def setNewName(self, newName):
        self.name = newName

    def eat(self):
        print("%s--在吃"%self.name)


bs = Bosi("印度貓")
print('bs的名字爲:%s'%bs.name)
print('bs的顏色爲:%s'%bs.color)
bs.eat()
bs.setNewName('波斯')
bs.run()

"""
輸出結果:
bs的名字爲:印度貓
bs的顏色爲:白色
印度貓--在吃
波斯--在跑
"""

多繼承

從圖中可以看出,所謂多繼承,即子類有多個父類,而且具備它們的特徵。 多繼承的格式以下:繼承

# 定義一個父類
class A:
    def printA(self):
        print('----A----')

# 定義一個父類
class B:
    def printB(self):
        print('----B----')

# 定義一個子類,繼承自A、B
class C(A,B):
    def printC(self):
        print('----C----')

obj_C = C()
obj_C.printA()
obj_C.printB()

"""
輸出結果:
----A----
----B----
"""

若是在上面的多繼承例子中,若是父類A和父類B中,有一個同名的方法,那麼經過子類去調用的時候,調用哪一個?接口

class A:
    def print(self):
        print('----A----')


class B:
    def print(self):
        print('----B----')

# 定義一個子類,繼承自A、B
class C(A,B):
    pass

obj_C = C()
obj_C.print()

"""
輸出結果:
----A----
"""

事實上調用的順序取決於C類先繼承的是哪一個類,先繼承的類會先被調用。 也可經過__mor__查看C類的對象搜索方法時的前後順序,接上面的代碼get

print(C.__mro__)
"""
輸出結果:
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
"""

重寫父類的方法

所謂重寫,就是子類中,有一個和父類相同名字的方法,在子類中的方法會覆蓋掉父類中同名的方法

class Cat:
    def sayHello(self):
        print("halou-----1")

class Bosi(Cat):

    def sayHello(self):
        print("halou-----2")
        
class Bali(Cat):

    def sayHello(self):
        print("halou-----3")

bosi = Bosi()
bali= Bali()
bosi.sayHello()
bali.sayHello()
"""
輸出結果:
halou-----2
halou-----3
"""

經過方法重寫咱們可讓父類的同一個行爲在子類中擁有不一樣的實現版本,當咱們調用這個通過子類重寫的方法時,不一樣的子類對象會表現出不一樣的行爲,這個就是多態(poly-morphism)

調用父類的方法

class Cat:
    def __init__(self,name):
        self.name = name
        

class Bosi(Cat):

    def __init__(self,name):
        # 調用父類的__init__方法1(python2)
        #Cat.__init__(self,name)
        # 調用父類的__init__方法2
        #super(Bosi,self).__init__(name)
        # 調用父類的__init__方法3
        super().__init__(name)
        self.color = 'yellow'

    def getName(self):
        return self.name

bosi = Bosi('xiaohua')

print(bosi.name)
print(bosi.color)
"""
輸出結果:
xiaohua
yellow
"""

總結:

  • 上文說過若是在子類中須要父類的構造方法就須要顯式地調用父類的構造方法,或者不重寫父類的構造方法,子類不重寫 __init __,實例化子類時,會自動調用父類定義的 __init __。
  • 若是子類重寫了__init__ 時,實例化子類,就不會調用父類已經定義的 __init __。
  • 若是重寫了__init __ 時,要繼承父類的構造方法,可使用以下方法:
    • super(子類,self).init(參數1,參數2,....)
    • 父類名稱.init(self,參數1,參數2,...)

多態

多態的概念是應用於Java和C#這一類強類型語言中,而Python崇尚「鴨子類型」。

相關文章
相關標籤/搜索