在C++、JAVA等程序開發時,每每會利用到接口。接口其實就是:本身提供給使用者來調用本身功能的方式\方法\入口。java
=================第一部分: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"); } } =================第四部分:Tester03.java package com.oo.demo; public class Tester03 { public static void main(String[] args) { System.out.println("===This is a person==="); IAnimal person = new Person2(); person.eat(); person.run(); person.sleep(); person.speak(); System.out.println("\n===This is a pig==="); IAnimal pig = new Pig(); pig.eat(); pig.run(); pig.sleep(); pig.speak(); } } java中的interface
接口提取了一羣類共同的函數,能夠把接口當作一個函數的集合。而後讓子類去實現接口中的函數。這樣作得好處也就是實現了歸一化。python
歸一化:只要是基於同一個接口實現的類,那麼這些類產生的對象在使用時,從用法來講是同樣的。linux
1)讓使用者無需關心對象的類,只須要知道這些對象都具有某些功能便可,下降使用難度。微信
2)讓高層的外部使用者能夠不加區分地處理全部接口兼容的對象集合。網絡
1、就好象linux的泛文件概念同樣,全部東西均可以當文件處理,沒必要關心它是內存、磁盤、網絡仍是屏幕(固然,對底層設計者,固然也能夠區分出「字符設備」和「塊設備」,而後作出針對性的設計:細緻到什麼程度,視需求而定)。
二、再好比:咱們有一個汽車接口,裏面定義了汽車全部的功能,而後由本田汽車的類,奧迪汽車的類,大衆汽車的類,他們都實現了汽車接口,這樣就好辦了,你們只須要學會了怎麼開汽車,那麼不管是本田,仍是奧迪,仍是大衆咱們都會開了,開的時候根本無需關心我開的是哪一類車,操做手法(函數調用)都同樣
在python中並無interface關鍵字,若是想去模仿接口概念,有兩種方法:app
方法一:藉助第三方模塊 http://pypi.python.org/pypi/zope.interfaceide
方法二:使用繼承。函數
1)繼承基類的方法,並作出本身的改變或擴展(代碼重用)。工具
實際這種用法意義不大,甚至每每是有害的,由於它會使得子類和基類出現強耦合。微信支付
2)聲明某個子類兼容於某基類,定義一個接口類,接口類中定義一些接口名(函數名)且並未實現接口功能,子類繼承接口類,並實現接口的功能。又稱爲接口繼承
# 正常實現調用 class Applepay: def pay(self,money): print('apple pay 支付了%s' %money) class Alipay: def pay(self,money): print('支付寶 支付了%s' %money) def payment(pay_obj,money): #實例化的另外一種調用,這個方法讓實例化的時候按照payment調用:就像下面的payment(apple1,200) pay_obj.pay(money) apple1 = Applepay() # apple1.pay(200) payment(apple1,200) """ apple pay 支付了200 """
# 2.有時候寫的時候會把方法寫錯,本身定義一個主動報錯 # 接口初成:手動報異常:NotImplementedError來解決開發中遇到的問題 class Payment: def pay(self): raise NotImplementedError #主動讓程序報錯 class Wechatpay(Payment): #微信支付 def pay(self,money): print('微信支付了%s元',money) class QQchatpay(Payment): #QQ支付 def fuqian(self,money): print('QQ支付了%s元',money) p = Wechatpay() p.pay(200) #不報錯 # 微信支付了%s元 200 q = QQchatpay() q.pay() #報錯
# 3.借用abc模塊來實現接口 #接口類(就是爲了提供標準,約束後面的子類) from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self,money): pass class Wechatpay(Payment): def fuqian(self,money): '''實現了pay的功能,可是方法名字不同''' print('微信支付了%s元'%money) class Alipay: def pay(self,money): print('支付寶 支付了%s' %money) # p = Wechatpay() #報錯了(由於上面定義了一個接口類,接口類裏面 # 定義了一個pay方法,而在下面的Wechatpay方法裏沒有pay方法,不能 # 調用,在接口類裏面約束一下,接口類裏的pay方法裏面不能寫其餘,直接pass) a = Alipay() a.pay(200) """ 支付寶 支付了200 """ # p = Payment() #接口類不能被實例化
由上面的例子能夠歸結,接口也就是作約束,讓下面的類的方法都按照接口類中給出的方法去定義。若是接口類裏有的方法類裏面沒有,則這個類不能被實例化。而abc模塊的使用,則說明了接口和抽象類的關聯性。
抽象類每每用來表徵對問題領域進行分析、設計中得出的抽象概念,是對一系列看上去不一樣,可是本質上相同的具體概念的抽象。在面向對象的概念中,全部的對象都是經過類來描繪的,可是反過來,並非全部的類都是用來描繪對象的,若是一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。
抽象類與普通類的特殊之處就是只能被繼承(抽象類是不完整的,它只能用做基類),不能被實例化。
在面向對象方法中,抽象類主要用來進行類型隱藏和充當全局變量的角色。下降使用者的使用複雜度,統一標準。
python的abc模塊中定義了抽象類的metaclass類ABCMeta,以及抽象方法裝飾器abstractmethod, abstractclassmethod, abstractstaticmethod,抽象property裝飾器abstractproperty等。能夠基於這些工具來實現本身的抽象類。
import abc #利用abc模塊實現抽象類 class Animal(metaclass=abc.ABCMeta): # 相似接口,只定義規範,不實現具體的代碼 @abc.abstractclassmethod def run(self): pass @abc.abstractclassmethod def eat(self): pass # 嘗試實例化抽象類:結果失敗 # animal = Animal() # TypeError: Can't instantiate abstract class Animal with abstract methods eat, run class People(Animal): def run(self): # 不符合規範,不容許實例化 print('people is walking') def eat(self): print('people is eating') class Pig(Animal): def run(self): print('Pig is running') def eat(self): print('Pig is eating') class Dog(Animal): def run(self): print('Dog is zouing') def eat(self): print('Dog is eating') peo1 = People() pig1 = Pig() Dog1 = Dog() peo1.eat() pig1.eat() Dog1.run() """ people is eating Pig is eating Dog is zouing """
#一切皆文件 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)
抽象類表示該類中可能已經有一些方法的具體定義,可是接口就僅僅只能定義各個方法的界面(方法名,參數列表,返回類型),並不關心具體細節。
抽象類的本質仍是類,指的是一組類的類似性,包括數據屬性(如all_type)和函數屬性(如read、write),而接口只強調函數屬性的類似性。
抽象類是一個介於類和接口之間的一個概念,同時具有類和接口的部分特性,能夠用以實現歸一化設計。
二、包含未實現的方法聲明;
三、派生類必須實現未實現的方法,抽象類是抽象方法,接口則是全部成員(不只是方法包括其餘成員)
一、類能夠實現無限個接口,但僅能從一個抽象(或任何其餘類型)類繼承,從抽象類派生的類仍可實現接口,從而得出接口是用來解決多重繼承問題的。
二、抽象類當中能夠存在非抽象的方法,可接口不能。
三、抽象類中的成員變量能夠被不一樣的修飾符來修飾,可接口中的成員變量默認的都是靜態常量(static final)。
四、抽象類是對象的抽象,然而接口是一種行爲規範。