1、抽象類 --類似介面
介面的概念:
自己提供給使用者來呼叫自己功能的方式\方法\入口,
1.1、java中介面 interface
=================第一部分:Java 語言中的介面很好的展現了介面的含義: IAnimal.java /* * Java的Interface介面的特徵: * 1)是一組功能的集合,而不是一個功能 * 2)介面的功能用於互動,所有的功能都是public,即別的物件可操作 * 3)介面只定義函式,但不涉及函式實現 * 4)這些功能是相關的,都是動物相關的功能,但光合作用就不適宜放到IAnimal裡面了 */ package com.oo.demo; public interface IAnimal { public void eat(); public void run(); public void sleep(); public void speak(); } =================第二部分:Pig.java:豬”的類設計,實現了IAnnimal介面 package com.oo.demo; public class Pig implements IAnimal{ //如下每個函式都需要詳細實現 public void eat(){ System.out.println("Pig like to eat grass"); } public void run(){ System.out.println("Pig run: front legs, back legs"); } public void sleep(){ System.out.println("Pig sleep 16 hours every day"); } public void speak(){ System.out.println("Pig can not speak"); } } =================第三部分:Person2.java /* *實現了IAnimal的“人”,有幾點說明一下: * 1)同樣都實現了IAnimal的介面,但“人”和“豬”的實現不一樣,為了避免太多程式碼導致影響閱讀,這裡的程式碼簡化成一行,但輸出的內容不一樣,實際專案中同一介面的同一功能點,不同的類實現完全不一樣 * 2)這裡同樣是“人”這個類,但和前面介紹類時給的類“Person”完全不一樣,這是因為同樣的邏輯概念,在不同的應用場景下,具備的屬性和功能是完全不一樣的 */ package com.oo.demo; public class Person2 implements IAnimal { public void eat(){ System.out.println("Person like to eat meat"); } public void run(){ System.out.println("Person run: left leg, right leg"); } public void sleep(){ System.out.println("Person sleep 8 hours every dat"); } public void speak(){ System.out.println("Hellow world, I am a person"); } }
1.2、為何要用介面
介面提取了一群類共同的函式,可以把介面當做一個函式的集合。
然後讓子類去實現介面中的函式。
這麼做的意義在於歸一化,什麼叫歸一化,就是隻要是基於同一個介面實現的類,那麼所有的這些類產生的物件在使用時,從用法上來說都一樣。
歸一化的好處在於:
歸一化讓使用者無需關心物件的類是什麼,只需要的知道這些物件都具備某些功能就可以了,這極大地降低了使用者的使用難度。
歸一化使得高層的外部使用者可以不加區分的處理所有介面相容的物件集合
就好象linux的泛檔案概念一樣,所有東西都可以當檔案處理,不必關心它是記憶體、磁碟、網路還是螢幕(當然,對底層設計者,當然也可以區分出“字元裝置”和“塊裝置”,然後做出針對性的設計:細緻到什麼程度,視需求而定)。
再比如:我們有一個汽車介面,裡面定義了汽車所有的功能,然後由本田汽車的類,奧迪汽車的類,大眾汽車的類,
他們都實現了汽車介面,這樣就好辦了,大家只需要學會了怎麼開汽車,那麼無論是本田,還是奧迪,還是大眾我們都會開了,開的時候根本無需關心我開的是哪一類車,操作手法(函式呼叫)都一樣
2、模仿interface
在python中根本就沒有一個叫做interface的關鍵字,如果非要去模仿介面的概念
可以藉助第三方模組:http://pypi.python.org/pypi/zope.interface
也可以使用繼承,其實繼承有兩種用途
一:繼承基類的方法,並且做出自己的改變或者擴充套件(程式碼重用):實踐中,繼承的這種用途意義並不很大,甚至常常是有害的。因為它使得子類與基類出現強耦合。
二:宣告某個子類相容於某基類,定義一個介面類(模仿java的Interface),介面類中定義了一些介面名(就是函式名)且並未實現介面的功能,子類繼承介面類,並且實現介面中的功能
class Interface:#定義介面Interface類來模仿介面的概念,python中壓根就沒有interface關鍵字來定義一個介面。 def read(self): #定介面函式read pass def write(self): #定義介面函式write pass class Txt(Interface): #文字,具體實現read和write def read(self): print('文字資料的讀取方法') def write(self): print('文字資料的讀取方法') class Sata(Interface): #磁碟,具體實現read和write def read(self): print('硬碟資料的讀取方法') def write(self): print('硬碟資料的讀取方法') class Process(Interface): def read(self): print('程式資料的讀取方法') def write(self): print('程式資料的讀取方法')
上面的程式碼只是看起來像介面,其實並沒有起到介面的作用,子類完全可以不用去實現介面 ,這就用到了抽象類
3、本節重點---抽象類
3.1、什麼是抽象類
與java一樣,python也有抽象類的概念但是同樣需要藉助模組實現,抽象類是一個特殊的類,它的特殊之處在於只能被繼承,不能被例項化
3.2、為什麼要有抽象類
如果說類是從一堆物件中抽取相同的內容而來的,那麼抽象類就是從一堆類中抽取相同的內容而來的,內容包括資料屬性和函式屬性。
比如我們有香蕉的類,有蘋果的類,有桃子的類,從這些類抽取相同的內容就是水果這個抽象的類,你吃水果時,要麼是吃一個具體的香蕉,要麼是吃一個具體的桃子。。。。。。你永遠無法吃到一個叫做水果的東西。
從設計角度去看,如果類是從現實物件抽象而來的,那麼抽象類就是基於類抽象而來的。
從實現角度來看,抽象類與普通類的不同之處在於:抽象類中只能有抽象方法(沒有實現功能),該類不能被例項化,只能被繼承,且子類必須實現抽象方法。這一點與介面有點類似,但其實是不同的,即將揭曉答案
4、在python中實現抽象類
#一切皆檔案 import abc #利用abc模組實現抽象類 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定義抽象方法,無需實現功能 def read(self): '子類必須定義讀功能' pass @abc.abstractmethod #定義抽象方法,無需實現功能 def write(self): '子類必須定義寫功能' pass # class Txt(All_file): # pass # # t1=Txt() #報錯,子類沒有定義抽象方法 class Txt(All_file): #子類繼承抽象類,但是必須定義read和write方法 def read(self): print('文字資料的讀取方法') def write(self): print('文字資料的讀取方法') class Sata(All_file): #子類繼承抽象類,但是必須定義read和write方法 def read(self): print('硬碟資料的讀取方法') def write(self): print('硬碟資料的讀取方法') class Process(All_file): #子類繼承抽象類,但是必須定義read和write方法 def read(self): print('程式資料的讀取方法') def write(self): print('程式資料的讀取方法') wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #這樣大家都是被歸一化了,也就是一切皆檔案的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read() print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type)
4.1、抽象類與介面
抽象類的本質還是類,指的是一組類的相似性,包括資料屬性(如all_type)和函式屬性(如read、write),而介面只強調函式屬性的相似性。
抽象類是一個介於類和介面直接的一個概念,同時具備類和介面的部分特性,可以用來實現歸一化設計
4.2、abc模組,Python 對於ABC的支援模組,定義了一個特殊的metaclass—— ABCMeta 還有一些裝飾器—— @abstractmethod 和 @abstarctproperty 。
import abc class A(metaclass=abc.ABCmeta): @abc.abstractmethod# 定義抽象方法,無需實現功能 def read(self): pass @abc.abstarctproperty# 定義抽象屬性
4.3、例題
通過定義抽象類,子類繼承抽象類,把子類規範化,如果想呼叫抽象類相同的函式,就必須和抽象類保持一致,否則出錯
規範子類
import abc class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod def run(self): pass @abc.abstractmethod def eat(self): pass class People(Animal): def run(self): print('people is walking') def eat(self): print('people is eating') class Dog(Animal): def run(self): print('dog is walking') def eat(self): print('dog is eating') class Pig(Animal): def run(self): print('pig is walking') def eat(self): print('pig is eating') people1 = People() dog1 = Dog() pig1 = Pig() people1.run() dog1.run() pig1.run()
4.4、抽象類的說明
不能被例項化,只能被繼承:上題中Aminal是抽象類 ,不能例項化 比如 animal=Aminal()
優點:規範化子類,降低使用的複雜度