1. 程式人生 > >面向物件概念及三大特點

面向物件概念及三大特點

面向物件:

面向物件的基本概念

面向物件   oop : object oriented programming
我們之前學習的程式設計方式就是面向過程的
面向過程和麵向物件,是兩種不同的程式設計方式
對比面向過程的特點,可以更好的瞭解什麼是面向物件

過程和函式(都是對一段功能的程式碼進行封裝)
過程:是早期的一個程式設計概念
    過程類似於函式,只能執行,但是沒有返回值
函式:不僅能執行,還可以返回結果(return)

面向過程 和 面向物件 的基本概念

1、面向過程:---側重於怎麼做?
1.把完成某一個需求的 所有步驟 從頭到尾 逐步實現
2.根據開發要求,將某些功能獨立的程式碼封裝成一個又一個函式
3.最後完成的程式碼,就是順序的呼叫不同的函式
特點:
1.注重步驟與過程,不注重職責分工
2.如果需求複雜,程式碼會變得很複雜
3.開發複雜專案,沒有固定的套路,開發難度很大

面向物件:--誰來做?
相比較函式,面向物件是更大的封裝,根據職責在一個物件中封裝多個方法
1.在完成某一個需求前,首先確定職責--要做的事(方法)
2.根據職責確定不同的物件,在物件內部封裝不同的方法(多個)即我們所說的函式。
3.最後完成程式碼,就是順序的讓不同的物件呼叫不同的方法
特點:
1.注重物件和職責,不同的物件承擔不同的職責
2.更加適合對複雜的需求變化,是專門應對複雜專案的開發,提供的固定套路
3.需要在面向過程的基礎上,再學習一些面向物件的語法


熟悉面向物件程式設計
python    java    c++

類:是對一群具有相同特徵或行為的事物的一個統稱,不能直接使用(比如:飛機制造圖紙不能飛上天)
    特徵:屬性
    行為:方法
物件:由類創建出來的一個具體的存在,可以直接使用(用圖紙製造出來的飛機可以飛上天)

注意!!!   在程式開發中:應該先有類 再有物件

類的設計
1.類名: 這類事物的名字,滿足大駝峰命名法
    大駝峰命名法
        每一個單詞的首字母大寫
        單詞與單詞只見沒有下劃線
2.屬性: 這個類創建出的物件有什麼樣的特徵
3.方法: 這個類創建出的物件有什麼樣的行為

注意!!!面向物件的三大特點:

1.封裝:根據職責將屬性和方法封裝到一個抽象的類中

2.繼承:實現程式碼的重用,相同的程式碼不需要重複的寫

3.多型:(以封裝和繼承為前提),不同的子類物件呼叫相同的方法,產生不同的執行結果

封裝

1.封裝是面向物件程式設計的一大特點

2.面向物件程式設計的第一步 將屬性和方法封裝到一個抽象的類中(為什麼說是抽象的,因為類不能直接使用)

3.外界使用類建立物件,然後讓物件呼叫方法

4.物件方法的細節都被封裝在類的內部

例1、

#定義一個Person類

class Person:
    def __init__(self, name, weight):
        # 初始化方法中增加兩個引數由外界傳遞
        # self.屬性 = 形參
        self.name = name
        self.weight = weight

    def __str__(self):
        # 輸出一段字串
        return '我的名字叫 %s 體重是 %.2f' % (self.name, self.weight)

    def run(self):
        print '%s 愛跑步' % self.name
        # 在物件方法的內部,是可以直接訪問物件的屬性
        self.weight -= 0.5

    def eat(self):
        print '%s 吃東西' % self.name
        self.weight += 1


xx = Person('小明', 75.0)
xx.run()
xx.eat()
print xx

# 同一個類創建出來的多個物件之間,屬性互補干擾
xm = Person('小麗', 45.0)
xm.run()
xm.eat()
print xm
print xx

例2:擺放傢俱

要求:

1.房子有戶型,總面積和傢俱名稱列表

新房子沒有任何的傢俱

2.傢俱有名字和佔地面積,其中

         床:佔4平米

         衣櫃:佔2平面

         餐桌:佔1.5平米

3.將以上三件傢俱新增到房子中

4.列印房子時,要求輸出:戶型,總面積,剩餘面積,傢俱名稱列表

class HouseItem:
    # 初始化方法
    def __init__(self, name, area):
        self.name = name
        self.area = area

    def __str__(self):
        return '[%s] 佔地 %.2f' % (self.name, self.area)

"""
傢俱名稱列表 []
"""

class House:
    def __init__(self, house_type, area):
        # 需要從外界傳遞進來的引數
        self.house_type = house_type
        self.area = area
        # 剩餘面積(新房子沒有任何傢俱,剩餘面積=總面積)
        self.free_area = area
        # 傢俱名稱列表
        self.item_list = []

    def __str__(self):
        return '戶型:%s\n總面積:%.2f[剩餘:%.2f]\n傢俱:%s' \
               % (self.house_type, self.area, self.free_area, self.item_list)

    def add_item(self, item):
        print '要新增 %s' % item
        """
        1.判斷傢俱的面積是否超過房子的面積,如果超過了,提示不能新增這個傢俱
        2.將傢俱的名稱 追加到傢俱名稱列表中去
        3.用房子的剩餘面積 - 傢俱的面積
        """
        if item.area > self.free_area:
            print '%s 的面積太大了,無法新增' % item.name
            # 如果不滿足,下方的程式碼就不執行
            return
        # 將傢俱的名稱新增到列表中
        self.item_list.append(item.name)
        # 計算剩餘面積
        self.free_area -= item.area

# 1.建立傢俱
bed = HouseItem('bed', 400)
print bed
chest = HouseItem('chest', 2)
print chest
table = HouseItem('table', 1.5)
print table

# 2.建立房子物件
my_home = House('兩室一廳', 400)
# 新增傢俱到房子裡面去
my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)
print my_home

注意:對於兩個類等的使用且相互有使用和被使用的關係,則被使用的類應該先開發

繼承

單繼承

繼承的概念:子類擁有父類的所有屬性和方法,目的是實現程式碼的重用,相同的程式碼不需要重複的寫。

繼承的語法

class 類名(父類):

         def 子類特有的方法

例1:

建立一個Animal類

class Animal(object):
    def eat(self):
        print '吃'

    def drink(self):
        print '喝'

    def run(self):
        print '跑'

    def sleep(self):
        print '睡'

#建立一個Cat類(其中Cat類是Animal類的子類)
# 子類機車父類的所有屬性和方法並且子類建立自己獨特的屬性方法
class Cat(Animal):
    def call(self):
        print '喵喵'

lily = Cat()
lily.eat()
lily.drink()
lily.run()
lily.sleep()
lily.call()

總結:

子類繼承自父類,可以直接享受父類中已經封裝好的屬性和方法

子類中應該根據自己的職責,封裝子類特有的屬性和方法

注意:

以上所說的繼承,可以有以下兩種說法,意思是一樣的

說法1:Cat類是Animal類的子類,Animal類是Cat類的父類,Cat從Animal類繼承

說法2:Cat類是Animal類的派生類,Animal類是Cat類的基類,Cat類從Animal類派生

應該注意:平級之間沒有任何必然聯絡

例2:

class Animal(object):
    def eat(self):
        print '吃'

    def drink(self):
        print '喝'

    def run(self):
        print '跑'

    def sleep(self):
        print '睡'


class Dog(Animal):
    def bark(self):
        print '旺旺'


lucy = Dog()

lucy.eat()

lucy.drink()

lucy.run()

lucy.sleep()

lucy.bark()

class Muyang(Dog):
    def speak(self):
        print '我會保護羊'

lily = Muyang()

lily.eat()

lily.drink()

lily.run()

lily.sleep()

lily.bark()

lily.speak()

總結:

繼承的傳遞性,子類擁有父類的父類的屬性和方法

繼承的傳遞性:(爺爺 父親 兒子)

1.Muyang類從Dog類繼承,Dog類又從Animal類繼承

2.那麼Muyang類就具有Dog類和Animal類的所有屬性和方法

子類Muyang擁有父類以及父類的父類中封裝的所有屬性和方法

例3:

重寫父類方法 1:

        1.覆蓋父類的方法

class Animal:
    def eat(self):
        print '吃'

    def drink(self):
        print '喝'

    def run(self):
        print '跑'

    def sleep(self):
        print '睡'

class Cat(Animal):
    # 子類擁有父類的所有屬性和方法
    def call(self):
        print '喵喵'

class Hellokitty(Cat):
    def speak(self):
        print '我可以說中文'

    def call(self):
        # 針對子類特有的需求,編寫程式碼,這種情況下子類重寫了父類的方法
        print '你很調皮'
       
kt = Hellokitty()
# 如果子類中,重寫了父類的方法
# 在執行中,只會呼叫在子類中重寫的父類的方法而不會呼叫父類的方法
kt.call()

例4:

重寫父類方法2:

        2.擴充套件父類的方法

class Animal:
    def eat(self):
        print '吃'

    def drink(self):
        print '喝'

    def run(self):
        print '跑'

    def sleep(self):
        print '睡'

class Cat(Animal):
    # 子類擁有父類的所有屬性和方法
    def call(self):
        print '喵喵'

class Hellokitty(Cat):
    def speak(self):
        print '我可以說中文'

    def call(self):
        # 針對子類特有的需求,編寫程式碼
        print '你很調皮'
        # 呼叫原本在父類中封裝的程式碼
        Cat.call(self)
        # 增加其他的子類程式碼
        print '@#¥Y%……&**&……%Y¥#@'

kt = Hellokitty()
kt.call()

總結:

     若重寫了父類的方法,則呼叫的時候只調用子類而不呼叫父類;

    但若子類在寫的時候還呼叫了父類,則相當於父類的擴充套件,呼叫的時候子類重寫的方法和父類已有的方法一起呼叫。

例5:

    定義屬性注意的事項:

class Bird:
    def __init__(self):
        self.hungry = True

    # 鳥吃過了以後就不餓了
    def eat(self):
        if self.hungry:
            print 'I am eating'
            self.hungry = False
        else:
            print 'No thanks'

class SongBird(Bird):
    def __init__(self):
        self.sound = 'Zd0ci!'
        #注意:
        Bird.__init__(self)

    def sing(self):
        print self.sound

little_bird = SongBird()
little_bird.eat()
little_bird.sing()

例5:

        多繼承可以讓子類物件,同時具有多個父類的屬性和方法

class A(object):
    def test(self):
        print 'A-----test 方法'

    def demo(self):
        print 'A-----demo 方法'

class B(object):
    def test(self):
        print 'B------test 方法'

    def demo(self):
        print 'B-------demo方法'

class C(B, A):
    """多繼承可以讓子類物件,同時具有多個父類的屬性和方法"""
    pass

# 建立子類物件
c = C()
c.test()
c.demo()

若將上面的class C(B, A)換成class C(A, B)

則結果為:

多型:

        (以封裝和繼承為前提),不同的子類物件呼叫相同的方法,產生不同的執行結果

例如:

定義一個類

人類
work(self):

建立兩個子類
程式設計師   設計師
這兩個子類呼叫了相同的方法

產生的結果如下:

class Dog(object):
    def __init__(self, name):
        self.name = name

    def work(self):
        print '%s 正在工作' % self.name


class xiaotiandog(Dog):
    # 父類方法不能滿足子類的方法,重寫game方法
    def game(self):
        # 在使用繼承時,子類擁有父類的所有屬性和方法
        print '%s 飛到天上玩...' % self.name


class Person(object):
    def __init__(self, name):
        self.name = name

    def game_with_dog(self, dog):
        print '%s 和 %s 快樂的玩耍' % (self.name, dog.name)
        # 讓狗玩耍
        dog.game()

# 1.建立一個狗物件
#wangcai = Dog('旺財')
wangcai = Xiaotiandog('旺財')
# 2.建立一個小明物件(小明是一個人)
xiaoming=Person('小明')
# 3.讓小明呼叫和狗玩的方法(把之前建立的狗物件傳遞進去)
xiaoming.game_with_dog(wangcai)
"""
案例小結:
Person類中只需要讓狗物件呼叫game方法(這是子類的父類中封裝的方法),而不關心具體是什麼狗
   game方法是在Dog父類中定義的
在程式執行時,傳入不同的狗物件的實參,就會產生不同的執行效果