面向對象三大特性——繼承高階(接口和抽象類)

1、接口(Interface)

  在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
java中interface

一、使用接口的好處

  接口提取了一羣類共同的函數,能夠把接口當作一個函數的集合。而後讓子類去實現接口中的函數。這樣作得好處也就是實現了歸一化。python

2、歸一化

  歸一化:只要是基於同一個接口實現的類,那麼這些類產生的對象在使用時,從用法來講是同樣的。linux

一、歸一化的好處

  1)讓使用者無需關心對象的類,只須要知道這些對象都具有某些功能便可,下降使用難度。微信

  2)讓高層的外部使用者能夠不加區分地處理全部接口兼容的對象集合。網絡

1、就好象linux的泛文件概念同樣,全部東西均可以當文件處理,沒必要關心它是內存、磁盤、網絡仍是屏幕(固然,對底層設計者,固然也能夠區分出「字符設備」和「塊設備」,而後作出針對性的設計:細緻到什麼程度,視需求而定)。

二、再好比:咱們有一個汽車接口,裏面定義了汽車全部的功能,而後由本田汽車的類,奧迪汽車的類,大衆汽車的類,他們都實現了汽車接口,這樣就好辦了,你們只須要學會了怎麼開汽車,那麼不管是本田,仍是奧迪,仍是大衆咱們都會開了,開的時候根本無需關心我開的是哪一類車,操做手法(函數調用)都同樣
接口兼容處理例子

3、python中實現接口

  在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模塊實現接口

  由上面的例子能夠歸結,接口也就是作約束,讓下面的類的方法都按照接口類中給出的方法去定義。若是接口類裏有的方法類裏面沒有,則這個類不能被實例化。而abc模塊的使用,則說明了接口和抽象類的關聯性。

4、抽象類

一、抽象類概念

  抽象類每每用來表徵對問題領域進行分析、設計中得出的抽象概念,是對一系列看上去不一樣,可是本質上相同的具體概念的抽象。在面向對象的概念中,全部的對象都是經過類來描繪的,可是反過來,並非全部的類都是用來描繪對象的,若是一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。

二、抽象類特色

  抽象類與普通類的特殊之處就是只能被繼承抽象類是不完整的,它只能用做基類),不能被實例化

三、抽象類用處

  在面向對象方法中,抽象類主要用來進行類型隱藏和充當全局變量的角色。下降使用者的使用複雜度,統一標準。

四、抽象類的實現

  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)
一切皆文件

5、抽象類與接口

  抽象類表示該類中可能已經有一些方法的具體定義,可是接口就僅僅只能定義各個方法的界面(方法名,參數列表,返回類型),並不關心具體細節。 

  抽象類的本質仍是類,指的是一組類的類似性,包括數據屬性(如all_type)和函數屬性(如read、write),而接口只強調函數屬性的類似性。

  抽象類是一個介於類和接口之間的一個概念,同時具有類和接口的部分特性,能夠用以實現歸一化設計。

一、抽象類和接口相同點

  一、不能實例化;

  二、包含未實現的方法聲明;

  三、派生類必須實現未實現的方法,抽象類是抽象方法,接口則是全部成員(不只是方法包括其餘成員)

二、不一樣點

  一、類能夠實現無限個接口,但僅能從一個抽象(或任何其餘類型)類繼承,從抽象類派生的類仍可實現接口,從而得出接口是用來解決多重繼承問題的。

  二、抽象類當中能夠存在非抽象的方法,可接口不能。

  三、抽象類中的成員變量能夠被不一樣的修飾符來修飾,可接口中的成員變量默認的都是靜態常量(static final)。

  四、抽象類是對象的抽象,然而接口是一種行爲規範。

相關文章
相關標籤/搜索