面向物件概念及三大特點
面向物件:
面向物件的基本概念
面向物件 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父類中定義的
在程式執行時,傳入不同的狗物件的實參,就會產生不同的執行效果