再次接觸物件導向

weixin_33670713發表於2017-07-27

    “物件導向”是專指在程式設計中採用封裝、繼承、抽象等設計方法。可是,這個定義顯然不能再適合現在情況。物件導向的思想已經涉及到軟體開發的各個方面。如,物件導向的分析(OOA,Object Oriented Analysis),物件導向的設計(OOD,Object Oriented Design)、以及我們經常說的面向物件的程式設計實現(OOP,Object Oriented Programming)物件導向是一種新興的程式設計方法,或者說它是一種新的程式設計範型,其基本思想是使用物件,類,繼承,封裝,訊息等基本概念來進行程式設計。


給你一個任務,你要思考怎麼做。

如果你的思維方式是:我先做什麼,再做什麼……這叫程式導向;

如果思維方式是:我先做一個什麼東西來做這件事,再做一個什麼東西來做那件事,然後它們怎麼相互配合……這叫物件導向。

封裝

    封裝就是定義一個類,然後給該類的 屬性(成員變數) 和方法加上訪問控制,使得該類的屬性和方法對於類外部來說,想可見的可見,不想可見的隱藏。所以,通過封裝這個手段,就抽象出來了事物的本質特性。

    將物件敏感的資料,封裝在類的內部,不讓外界直接訪問;而是通過定義的set/get方法來間接訪問內部的資料的過程,此時,就可以在set/get方法中,新增條件限制程式碼!�正常變數,沒有任何限制,想怎麼訪問怎麼訪問‚約定了以一個下劃線開頭的變數,是私有變數,外界不要直接使用,如_nameƒ兩個下劃線開頭的屬性,表示當前類的私有屬性,外界不能訪問__age

classPerson:

def__init__(self,heigh,name, age):

self.heigh = heigh

self._name = name

self.__age = age

defset_age(self, age):

ifage >=0andage <=100:

self.__age = age

else:

print("設定的年齡不合法...")

defget_age(self):

returnself.__age

def__str__(self):

return"姓名:%s;年齡:%s"% (self.__name,self.__age)

p = Person(175,"tom",12)

print(p.heigh)

print(p._name)可以輸出,但不建議

print(p.__age)報錯,會出現不存在__age的說法,應該應用一下用法:

p.set_age(1200)

print(p。Get_age)

對上面進行進一步的解釋:

   所謂封裝,就是將屬性和方法捆綁到一起,封裝到一個物件中去,簡單的說,你是人,你有許多屬性,比如說你的姓名,年齡,身高,體重,性別,性格,愛好等等,這是屬性;而同時,你又會吃飯,睡覺,工作,學習,做事情,這些是方法,是你所具有的;同時將屬性和方法封裝到一個類中去,就能很完美的描述這個類的特徵了,同時,它所具有的方法也就一起整合到類中,方便使用。

為什麼要加上訪問控制?

是,有些東西是很關鍵很機密的,不想隨便被使用,被改變,被訪問。

二是,可能這個東西不是很關鍵機密,訪問和改變也無所謂,但是,因為有些屬性和方法,它們對於外部來說,是無關的沒用的,但是對於我自己這個類來說,是必要的,因為可能在我自己這個類中要使用它們,這個時候,進行隱藏,不讓外部看,好處就是,如果將這些不必要的內容也暴露給外部的話,那麼在使用的時候,使用者會被迷惑,因為這個東西對他沒用,但是又可以呼叫,訪問,而且他又不知道又沒有用,但是如果進行隱藏,不給外部檢視,那麼就很清晰了,因為這樣一來,只要是對外暴露的屬性方法,都是有用的,你想一下,JDK的類庫裡面的那些類,比如String類,對外暴露的屬性和方法,哪個是無用的?這也是一種良好的程式設計習慣和規範。


封裝是把過程和資料包圍起來,對資料的訪問只能通過已定義的介面。物件導向計算始於這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的物件,這些物件通過一個受保護的介面訪問其他物件。(採自Java面試題)


繼承

    繼承是指一個物件直接使用另一物件的屬性和方法。繼承可以使得子類具有父類的各種屬性和方法,而不需要再次編寫相同的程式碼。在令子類繼承父類的同時,可以重新定義某些屬性,並重寫某些方法,即覆蓋父類的原有屬性和方法,使其獲得與父類不同的功能。

    同類事物具有共同性,在同類事物中,每個事物又具有其特殊性。運用抽象的原則捨棄物件的特殊性,抽取其共同性,則得到一個適應於一批物件的類,這便是基類(父類),而把具有特殊性的類稱為派生類(子類),派生類的物件擁有其基類的全部或部分屬性與方法,稱作派生類對基類的繼承。語法層面上講,繼承就是派生類擁有父類的資料、方法,又添了點自己的東西,所謂子承父業,發揚光大。

父類:被繼承的類,稱為父類,也稱為基類、超類,子類繼承父類,父類還可以繼承父類

子類:繼承了父類的類,稱為子類,也稱為派生類

子類擁有父類的公共屬性和公共方法,如下面程式碼:

classA:

defeat(self):

print("吃飯")

classB(A):

defplay(self):

print("遊戲中...")

classC(B):

defsleep(self):

print("休息休息")

classD(C):

pass

d = D()

d.eat()程式碼中B擁有A的方法,C擁有A,B的方法,D擁有ABC的方法

d.play()即D繼承了以上父類的所有方法

d.sleep()

一個子類,可以同時繼承多個父類

多繼承,反應了生活中表現的多個角色如下面程式碼:

#定義了一個基礎類

classPerson(object):

def__init__(self):

self.name ="tom"

classStudent(Person):

defeat(self):

print("吃食堂....")

defrespect(self):

print("尊師重道")

classSon(Person):

defeat(self):

print("吃美食...")

deffealty(self):

print("尊老愛幼")

# User型別,繼承了兒子型別、學生型別

#同時擁有兒子型別和學生型別中所有的公共屬性和方法

classUser(Son,Student):

pass

#建立物件

u = User()

u.respect()# u是學生角色

u.fealty()# u是兒子角色

    對於吃飯這個方法,如果繼承的多個父類中,出現了相同的屬性和方法,就會執行方法或者屬性的搜尋過程,搜尋到對應的屬性和方法,立即執行,中斷搜尋所以儘量不要在多個類中出現名稱相同的屬性和方法

屬性和方法的搜尋過程,可以通過  型別.__mro__魔法屬性進行檢視,

基本原則是:優先繼承,優先執行

u.eat()#即執行son的角色

print(User.__mro__)# method from object

方法重寫:子類中,重新定義父類中已經存在的方法    子類-父類,兩個實現了繼承關係的型別,才會有方法重寫如果方法進行了重寫,在子類物件執行這個方法時,優先執行重寫的方法。如果子類沒有重寫這個方法,在執行時就會執行從父類中繼承過來的方法

classPerson:

defeat(self,food):

print("吃飯吃飯..餓肚肚..吃%s"% food)

classMan(Person):

defeat(self,food):

print(">>>>>>>>>>餓肚肚,吃飯飯,吃%s"% food)

p = Person()

p.eat("魚香肉絲")

m = Man()

m.eat("烤全羊")#優先執行自身的方法的程式碼


方法過載:在一個型別中,出現了相同名稱,不同引數的函式/方法,稱為方法過載

    目的:在執行的過程中,通過引數的不同,來執行不同的程式碼,實現不同的功能

python中,已經實現了,【可變引數、關鍵字引數】--【我不需要方法過載了!】

python又針對屬性訪問函式,進行了相同名稱函式的定義 —— 偽方法過載

偽方法過載的目的:配合封裝,隱藏資料訪問方法的底層實現!

在下面程式碼講解

classUser:

def__init__(self,name):

self.__name = name

@property

defname(self):

returnself.__name

@name.setter#旁邊執行了兩個name方法,即叫做(偽)方法過載

defname(self,n):

self.__name = n

u = User("tom")

u.name ="jerry"#資料訪問方法被隱藏了,方法當成了屬性來進行執行

print(u.name)#資料訪問方法被隱藏了,方法當成了屬性來進行執行


多型

多型:程式在執行的過程中,根據執行條件的不同,動態執行不同的操作程式碼的過程稱為程式執行時多型。請看一下程式

#定義一個人的型別

classPerson:

# name姓名age年齡health健康值【0~50極度虛弱,51~70亞健康,71~85健康,86~100強壯】

def__init__(self,name,age,health):

self.name = name

self.age = age

self.health = health

#康復的方法

defrecure(self):

print("[%s]康復了,當前健康值%s"% (self.name,self.health))

classMan(Person):

def__init__(self,name,age,health):

Person.__init__(self,name,age,health)

defrecure(self):

print("%s哇咔咔,康復了"%self.name)

classWomen(Person):

def__init__(self,name,age,health):

Person.__init__(self,name,age,health)

defrecure(self):

print("[%s]死鬼,終於康復了..."%self.name)

classAnimal:

# name姓名age年齡health健康值【0~50極度虛弱,51~70亞健康,71~85健康,86~100強壯】

def__init__(self,name,age,health):

self.name = name

self.age = age

self.health = health

#康復的方法

defrecure(self):

print("[%s]嘿嘿嘿,終於康復了,當前健康值%s"% (self.name,self.health))

#定義人民醫院

classHospital:

def__init__(self):

self.name ="人民醫院"

defcare(self,person):

#型別判斷,判斷變數person是否Person型別

ifisinstance(person,Person):

ifperson.health >0andperson.health <=50:

print("手術......")

person.health +=30

person.recure()

elifperson.health >50andperson.health <=70:

print("輸液......")

person.health +=15

person.recure()

else:

print("健康")

else:

print("不好意思,請出門左轉,哪裡是獸醫院")

#醫院物件

hospital = Hospital()

#生病的人

old_wang = Person("王先生",58,30)

mrs_li = Women("李夫人",28,56)

mr_li = Man("李先生",30,60)

#在這裡,hospital由於物件的不同執行不同的

程式碼動態執行不同的操作程式碼的過程稱為程式執行時多型

hospital.care(mrs_li)

#呼叫了治療的方法

hospital.care(old_wang)

hospital.care(mr_li)

a = Animal("tom",22,10)

hospital.care(a)


執行結果:

手術......

[王先生]康復了,當前健康值60

輸液......

[李夫人]死鬼,終於康復了...

輸液......

李先生哇咔咔,康復了

不好意思,請出門左轉,哪裡是獸醫院

Process finished with exit code 0


再來一個例子:

classMan:

defintro(self):

print("我的姓名是XXXXXXXXXXXXXXXXXXXXXX")

classWomen:

defintro(self):

print("我的姓名是oooooooooooooooooooooo")

defintroduction(person):

person.intro()

m = Man()

w = Women()

introduction(m)#由於m和w的不同,函式執行兩個不同程式碼,這個過程就可以

introduction(w)#稱之為多型

相關文章