如何理解“物件導向”

戴德滿發表於2019-03-04

理解物件導向,首先理解要它的基礎概念:

物件導向是將現實問題構建關係,然後抽象成 類 ( class ) ,給類定義屬性和方法後,再將類例項化成 例項 ( instance ) ,通過訪問例項的屬性和呼叫方法來進行使用。

在不同的語言中,物件的定義範圍不同。在 Python 中 類 和 類的例項 都稱為 物件 ( Object ),因為 Python 的類是更頂級的 type 例項化後的物件;而在 Java 等靜態語言中,一般把類的例項稱為物件。


理解了理論知識後,接著通過例子,再理解物件導向的三大特徵:封裝、繼承、多型。

下邊我們把女媧造人的神話故事用物件導向來敘述一遍:

假設我們是女媧(程式設計者),我們突然有個想法,想造一群和自己差不多的小人,小人需要有男女兩種性別,外觀和行為也有一些差異。那首先我們分析出,不管什麼性別,都應該有四肢,所以我們先仿照自己的構造,在腦海中構思泥人的樣子(抽象成基類),然後先賦予泥人一些共有的行為(定義類的例項方法):

class Human(object):

    def __init__(self, name='泥人'):
        // 有個名字,有兩隻手,兩條腿
        self.name = name
        self.hands = 2
        self.legs = 2

    def introduce_self(self):
        // 介紹自己
        print('我是%s' % self.name)
複製程式碼

然後我們先捏3個泥人,並給他們取了不同的名字:

>>> a = Human('大強子')
>>> b = Human('二狗子')
>>> c = Human('三愣子')
複製程式碼

我們讓其中一個人介紹自己:

>>> a.introduce_self()
我是大強子
複製程式碼

然後我們繼續完成想法,需要給泥人增加兩種性別,並且異性之間能結婚,我們開始在剛才泥人模型的基礎上(繼承於基類),構思出兩種性別的泥人的區別(設定不同的屬性),然後讓他們都可以工作,但工作的內容不一樣(呼叫相同的方法出現不同結果,是多型性),並決定讓男人可以娶女人(將這個行為定義為男人的方法)。

import random

class Female(Human):

    def __init__(self, name):
        // 呼叫父類的初始化方法,依然有名字、兩隻手、兩條腿
        super().__init__(name)
        // 頭髮和力量進行隨機取值
        self.hair = random.randint(3, 5)
        self.power = random.randint(1, 3)
        // 是否已婚
        self.married = False

    def work():
        print('%s採摘了一些果子' % self.name)

class Male(Human):

    def __init__(self, name):
        super().__init__(name)
        self.hair = random.randint(0, 2)
        self.power = random.randint(2, 5)
        self.married = False

    def work():
        print('%s出去打獵了一天' % self.name)

    def marry(self, other):
        // 判斷自己或對方是否已結婚,否則丟擲異常
        if self.married is True or other.married is True:
            raise ValueError('法律不支援多次結婚')
        // 判斷對方是否是女性,否則丟擲異常
        if instance(other, Female):
            self.married = True
            other.married = True
        else:
            raise TypeError('法律不支援同性結婚')
複製程式碼

然後我們就可以讓小人活動起來:

>>> a = Male('大強子')
>>> b = Male('二狗子')
>>> c = Female('翠花')
>>> for h in [a, b, c]:
...     // 呼叫父類的方法
...     h.introduce_self()
我是大強子
我是二狗子
我是翠花
>>> for h in [a, b, c]:
...     // 多型性使相同的方法產生不同的結果
...     h.work()
大強子出去打獵了一天
二狗子出去打獵了一天
翠花采摘了一些果子
>>> a.marry(c)
>>> a.married
True
>>> c.married
True
>>> b.marry(c)
ValueError: 法律不支援多次結婚
>>> b.marry(a)
TypeError: 法律不支援同性結婚
複製程式碼


看到這裡你應該會發現,物件導向是更接近人類思維模式的程式設計思想,在這種可以具象化的需求中,可以極大簡化其中的邏輯,讓我們關注於設計物件的屬性和方法。

雖然你確實可以通過寫一長串函式來達到同樣的效果,那實際是另一種程式設計思想:程式導向,通過函式實現過程中一系列的功能,最後按順序組合後達成需求。

並不是說 程式導向 弱於 物件導向,而是在不同的需求中要選擇最合適的設計思路,比如在設計順序執行的指令碼中,明顯程式導向的設計思路是更加適合,如果我們還去定義類就有些累贅了。

這也是剛入門常有的疑問,發現物件導向還要定義類,很是麻煩,這實際是因為沒有遇到適合物件導向的需求導致的。

如果是擁有複雜關係的需求,我們就應該儘可能將互相有關聯的行為抽象成類,比如每一個網頁,網頁中每一個元件 等等。實際上物件導向幫助我們在十萬行程式碼的大型專案中,仍然可以遊刃有餘,正因為如此,才能發展為目前應用最為廣泛的程式設計思想。



最後,不管是面向什麼程式設計,終究還是要面向人生

歡迎關注我的微信公眾號:面向人生程式設計

如何理解“物件導向”

無論什麼樣的程式設計思想,都不該只存留在程式碼之中,更應伴隨於整個人生旅途,這個公眾號不只聊技術,還會聊產品/網際網路/經濟學等廣泛話題,所以也歡迎非程式設計師關注。


相關文章