關於抽象類和接口的初步理解

關於抽象類和接口的初步理解

什麼是抽象類

  1. 抽象類是指在 class 前加了 abstract 關鍵字且存在抽象方法(在類方法 function 關鍵字前加了 abstract 關鍵字)的類。php

  2. 抽象類不能被直接實例化。抽象類中只定義(或部分實現)子類須要的方法。子類能夠經過繼承抽象類並經過實現抽象類中的全部抽象方法,使抽象類具體化。編程

  3. 若是子類須要實例化,前提是它實現了抽象類中的全部抽象方法。若是子類沒有所有實現抽象類中的全部抽象方法,那麼該子類也是一個抽象類,必須在 class 前面加上 abstract 關鍵字,而且不能被實例化。
    引用連接函數

  1. 接口(Interface)—— 定義行爲this

  2. 抽象類(Abstract Class) —— 實現行爲.net

  3. 具體類(class)——執行行爲
    引用連接設計

  1. 抽象類就是一個類的服務提供商,擁有衆多服務,你不用必須用,當須要的時候你來用就能夠,若是你以爲不提供服務不滿意,你還能夠本身來作。code

  2. 抽象方法是必須實現的方法。就象動物都要呼吸。可是魚用鰓呼吸,豬用肺呼吸。
    動物類要有呼吸方法。怎麼呼吸就是子類的事了。對象

引用連接blog

爲何要使用抽象類

按照我目前的知識理解:繼承

  1. 保持程序的一致性

  2. 抽象類限制了實現的方法,也是爲了保持一致性

  3. 增長代碼重用性,例如一些公共類不須要實現,只須要調用裏面的方法就能夠了。

  4. 如今有不少討論和建議提倡用interface代替abstract類,二者從理論上能夠作通常性的混用,可是在實際應用中,他們仍是有必定區別的。抽象類通常做爲公共的父類爲子類的擴展提供基礎,這裏的擴展包括了屬性上和行爲上的。而接口通常來講不考慮屬性,只考慮方法,使得子類能夠自由的填補或者擴展接口所定義的方法,就像JAVA王子所說的事件中的適配器就是一個很好的應用。

用一個簡單的例子,好比說一個教師,咱們把它做爲一個抽象類,有本身的屬性,好比說年齡,教育程度,教師編號等等,而教師也是分不少種類的,咱們就能夠繼承教師類而擴展特有的種類屬性,而廣泛屬性已經直接繼承了下來。

而接口呢~仍是拿教師作例子,教師的行爲不少,除了和普通人相同的之外,還有職業相關的行爲,好比改考卷,講課等等,咱們把這些行爲定義成無body的方 法,做爲一個集合,它是一個interface。而教師張三李四的各自行爲特色又有不一樣,那麼他們就能夠擴展本身的行爲body。從這點意義上來講,interface偏重於行爲。

引用連接

怎樣使用抽象類

<?php
    abstract class  Shape{  //這是一個抽象類,不能實例化
        protected  $color;  //抽象類裏面通常都是使用protected來保護屬性,這是封裝的意義
        
        public function __construct($color = 'red') {   //抽象類可使用構造方法,主要是爲了方便代碼重用,構造方法裏面也可使用默認參數,當沒有配置參數的時候,就會使用默認的參數,寫法如上
            $this->color = $color;
        }
        
        public function getColor() {  //只是爲了演示須要的一個方法
            return $this->color;
        }
        
        abstract public function getArea();  //構造方法是爲了限制代碼,對於繼承這個構造類的子類,必須限制擁有這個構造方法,主要爲了保持代碼一致性。
    }
    
    class Square extends Shape{
        protected  $length = 4;
        public function getArea() {
            return pow($this->$length, 2);
        }
    }
    
    class Circle extends Shape{ //這裏由於沒有構造方法getArea,因此代碼容許會報錯的。
        
    }
    
    $shape = new Square();
    var_dump($shape);
?>

接口和抽象類

  1. 抽象類不能被直接實例化,抽象類中只定義子類須要的方法,子類能夠繼承而且經過實現其中的抽象方法,使抽象類具體化。例如一個名爲media的類,他是用於描述各類公開出版的共同性質,由於media不表示真實的實體,而是一些類似實體的泛化表示,因此不實例化,這樣就須要聲明爲抽象類,而後再由各類的派生的Media類繼承此抽象類

  2. 抽象類的每一個子類都必須實現抽象類中的全部抽象方法,或者把他們自身也聲明爲抽象方法。

  3. 擴展類不只僅負責簡單實現抽象類的方法,還必須從新聲明方法,新的方法不能比抽象方法的訪問控制更嚴格,新的實現方法的參數個數應該和抽象方法的參數個數同樣。

  4. 接口定義了實現某種服務的通常規範,聲明瞭必須的函數和常量,可是不指定如何實現。關鍵是要創建必須實現的一組通常原則,只有知足了這些原則才能說實現了這個接口。

  5. 抽象類提供了具體實現的標準,而接口則是純粹的模板。接口只能定義功能而不包含實現的內容。

  6. 任何實現接口的類都要實現接口中所定義的全部方法,不然類必須聲明爲abstract。

  7. 實現接口的類接受他的繼承的類以及實現的接口的類型。

何時用接口,何時用抽象類

  • 若是要建立一個模型,這個模型將由一些緊密相關的對象引用,就能夠採用抽象類,若是要建立將由一些不想關的對象採用的功能,應該用接口。

  • 若是必須從多個來源繼承行爲,就是用接口。

  • 若是知道全部類都會共享一個公共的行爲實現,就使用抽象類,並在其中實現行爲。接口沒法實現。

  • 一個類只能extends一個父類,但能夠貫徹多個接口。

接口做用一:

接口類就是一個類的領導者,指明方向,子類必須完成它指定方法。

當有不少人一塊兒開發一個項目時,可能都會去調用別人寫的一些類,那你就會問,我怎麼知道他的某個功能的實現方法是怎麼命名的呢,這個時候php接口類就起到做用了,當咱們定義了一個接口類時,它裏面的方式是下面的子類必須實現的,好比

interface Shop
{
public function buy($gid);
public function sell($gid);
public function view($gid);
}
class BaseShop implements Shop
{
    public function buy($gid)
    {
        echo '你購買了ID爲 :' . $gid . '的商品';
    }

    public function sell($gid)
    {
        echo '你購賣ID爲 :' . $gid . '的商品';
    }

    public function view($gid)
    {
        echo '你瀏覽了ID爲 :' . $gid . '的商品';
    }
}

接口做用二:

有時候,咱們須要設計一個物品,好比shape,這個shape有不一樣的形狀,有不一樣的顏色,可做不一樣的運動,等等。固然咱們能夠把這些都放在一個類裏面,但這樣,如前面說的,只是過程編程,不是OO編程。你會說,像上面例子同樣,作一個抽象類,而後在子類裏實現全部的功能。好象不錯,進步了。這樣子類裏面要實現形狀,顏色,運動等功能,OK嗎?記住,OO裏面還有一條原則,爲了最大程度的作到代碼重用,一個類裏最好只實現一個功能,也就是說,一個類作形狀,一個類作顏色,一個類作運動 。這樣若是其餘的類要用到顏色的功能時,咱們就能夠重用這個顏色類,同理,這樣咱們能夠很容易的重用運動類,形狀類,等等。

但這樣問題出來了,如今咱們要用到上面全部的功能,但又分散在三個類裏面,怎麼辦?這時咱們就要用到抽象類和接口了。選定一個跟shape關聯最大的一項–形狀,把它作成抽象類, 其餘兩樣,把它們作成接口,而後在子類裏面extends一個抽象類,再implements兩個接口就好了。如:

class Square extends Shape implements 顏色, 運動, ... {
...
}

抽象類做用一:

抽象類就是一個類的服務提供商,擁有衆多服務,你不用必須用,當須要的時候你來用就能夠,若是你以爲不提供服務不滿意,你還能夠本身來作。

這裏是一個例子,想上面同樣我定義了一個商店類,抽所了它全部像的部分,買(buy),賣(sell),看(view),而且抽象類裏都實現了這些方法,那麼繼承它的子類就自動得到了這些方法,子類就作它本身獨特的東西,減小代碼的重複,提升複用性。

abstract class BaseShop
{
    public function buy($gid)
    {
        echo '你購買了ID爲 :' . $gid . '的商品';
    }

    public function sell($gid)
    {
        echo '你購賣ID爲 :' . $gid . '的商品';
    }

    public function view($gid)
    {
        echo '你瀏覽了ID爲 :' . $gid . '的商品';
    }
}

class BallShop extends BaseShop
{
    var $itme_id = null;

    public function __construct()
    {
        $this->itme_id = 2314;
    }

    public function open()
    {
        $this->sell($this->itme_id);
    }
}

抽象類做用二:

在抽象類裏面設置抽象方法

在oo設計時,會把一些通用的方法放在一個類裏,但考慮到子類繼承時的差別性,又不能把它事先實現,就只好用到這個抽象類或接口了。這裏很清楚的顯示了在抽象類裏,咱們貫徹了設原用到點setCenter()的方法,這樣,當子類繼承它時,就不用再重複寫這個設原點的方法了。那麼爲何draw的方法要設定成抽象方法呢?這是由於不一樣的子類要用不一樣的實現方法。

abstract class Shape
{
    function setCenter($x, $y)
    {
        $this->x = $x;
        $this->y = $y;
    }

    abstract function draw();

    protected $x, $y;
}

參考:http://chengxudaren.com/index.php?act=article&op=detail&a_id=152

相關文章
相關標籤/搜索