首頁  >  文章  >  後端開發  >  PHP基礎教學十二之抽象、接口

PHP基礎教學十二之抽象、接口

黄舟
黄舟原創
2017-03-01 10:04:091253瀏覽

本節講解的內容

  • #介面

##final的使用

類別常數

前言

在PHP中的物件導向是透過定義類,來完成物件的範例化,而PHP的抽象類別和介面類別可以說是類別的一種規範,透過定義這兩種類別來對類別進行強制約束,雖然這兩種都是對類別的約束,但本質上他們還是有區別的。

抽象類別

抽象類別的概念我們可以用動物的繼承關係來說明問題,當我們寫父類別Animal類別時,其中有兩個方法sleep (),eat(),因為不知道具體是什麼動物而無法確定方法中寫什麼內容。這是我們就可以用抽象類別進行實作。

<?php
//通过关键字abstract来声明抽象类
abstract class Animal{
    protected $name;
    protected $age;
    //声明该方法是抽象方法
    abstract public function sleep();
    abstract public function eat();
}

當父類別的一些方法不能確定的時候,可以用abstract關鍵字來修飾該方法,稱為抽象方法,而用abstract修飾的類別稱為抽象類別。

基本語法:

abstract  class  类名{
    abstract  访问修饰符   函数名(参数列表);
}

在開發中當我們想讓繼承該類別的所有子類別都重寫該類別的方法,就可以用抽象方法來實作。
    抽象類別就好比某個東西的架子也可以說是一個模板,有了模板就可以根據模板實現具體的功能。
  • ,而模板和具體事物的這種關係是透過繼承類別傳遞的。就好比一台電腦,透過模板來製作一台台電腦。而抽象類別定義出來就是需要被繼承的。

    <?php
    
    abstract class Animal{
        protected $name;
        protected $age;
    
        abstract public function sleep();
        abstract public function eat();
    }
    class Dog extends Animal{
    
    }
    ......结果........
    Fatal error: Class Dog contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Animal::sleep, Animal::eat) 
    in D:\mywamp\Apache24\htdocs\zendstudio\yunsuanfu\chouxiang.php on line 13

  • 當一個類別繼承了抽象類別後,在子類別中就需要實作父類別的所有抽象方法
  • 上面報的錯誤就是說在父類別中包含2個抽象方法,子類別必須實作該抽象方法。而關於抽象類別的特點可以總結如下:

  • 抽象類別是不能被範例化的,不能透過抽象類別來new一個對象,會報一個Cannot instantiate abstract class錯誤。

  • 抽象類別中可以沒有抽象方法的,在抽象類別中都是普通方法,但是類別名稱是用abstract修飾的。

    <?php
    abstract class Animal{
        protected $name;
        protected $age;
        public function sleep(){
    
        }
        public function eat(){
    
        }
    }

  • 抽象類別可以有普通的成員方法,屬性等

    <?php
    abstract class Animal{
        protected $name;
        protected $age;
    
        abstract public function sleep();
        abstract public function eat();
    
        public function cry(){
    
        }
    }

    如果一個類別中有抽象方法,那麼這個類別必須是抽象類別。
  • 抽象方法是沒有方法體的
  • abstract public function eat();
沒有{},也就是說沒有方法體。

一個類別繼承了抽象類,則子類別必須實作抽象類別的所有抽象方法,或者子類別自己也宣告為抽象類別

#介面

介面的初衷和抽象類別是一樣的,不知道方法裡面怎麼實作的時候可以用介面來實作。而介面的定義是:給一些沒有實現的方法,封裝到一起,到某個類別要使用的時候,再根據具體情況把這些方法寫出來,介面的出現體現了高內聚低耦合的特徵。

<?php

interface iTechnical{
    public function fly();
}

基本語法:

interface 接口名{
    //方法, 在接口中,所有的方法都不能有方法体, 即都是抽象方法
}
介面類別和抽象類別大致一樣,那介面具體是什麼呢?上面有說到抽象類別就好比一台筆記本的架子、模板,然後根據模板創建具體的筆記本,而沒有筆記本都有幾個usb接口,而接口類就好比這些筆記本上的接口,是一個擴展的實現。就像動物一樣都繼承了動物特有的特性吃,睡等,但是突然一隻動物在別的地方實現了寫字的本領,這種本領就是透過介面進行擴充的。

介面的命名一般是在類別名稱的第一個字母是小寫的i開頭。在

介面類別中所有的方法都預設是抽象方法。

所以並不需要寫abstract來宣告。

介面的實作

  • 我們定義一個介面當然是讓別的類別去實現的,這裡說的是實現,而不是繼承,介面和別的類之間是實現的關係,也就是類別實現了某一接口,用implements關鍵字實現。

    interface iTechnical{
        public function fly();
    }
    
    class Dog implements iTechnical{
        public function fly(){
            echo &#39;<br>飞&#39;;
        }
    }

    當然在子類別中必須實作介面中所有的方法。
  • 關於介面的特性有以下幾點:

  • 介面類別和抽象類別一樣是不能被實例化的。

  • 介面中所有的方法都不能有主體,因為都是抽象方法。

  • 一個類別可以實作多個介面,逗號隔開(繼承只能是一個)

    class Dog implements 接口1,接口2{
    
    }

  • 介面中可以有屬性,但只能是常數,預設是public, 但不能用public 明確修飾

介面中的方法都必須是public的,介面就是用來繼承的所以用public,如果沒有寫修飾符,預設是public

一個介面不能繼承其它的類別,但是可以繼承別的介面

#########抽象和介面的區別#########在PHP中繼承是單繼承的,也就是一個類別最多只能有一個父類,而這種單一繼承的機制可以保證類別的純潔性。但是這種機制對子類別功能擴展有一定的影響。 ###

接口的出现可以说是对继承的一种补充,继承是层级的,不太灵活,而接口却没有它比抽象要灵活的多。并且实现接口在不打破继承关系的前提下,对子类的功能进行扩充。
它们两个的关系图可以理解为这样:
PHP基礎教學十二之抽象、接口

final的使用

在上面的介绍中每个类都是可以被继承的,如果我们有一个类,我们不想让子类去重写里面的某个方法,或者不想让别的类去继承该类,就可以用到关键字final。final中文意思:最后的,最终的,可以用来修饰类或者方法。

final可以修饰方法或者类,如果修饰方法,则表示该方法不可以被继承类去重写,如果final 修饰了一个类,则表示该类不可以被继承。

基本语法:

final  class   类名{
}
class 类名{
    final 访问修饰符 function 函数名(形参){}
}

修饰类和修饰方法。

<?php

    final class A{

    }

    class B extends A{

    }
    .....结果.....
    Class B may not inherit from final class (A)

不能继承用final修饰的类。

<?php

    class A{
        final public function sum($num1,$num2){
            return $num1 + $num2;
        }

    }

    class B extends A{
        public function sum($num1,$num2){
            return $num1 + $num2;
        }
    }
    .....结果.....
    Cannot override final method A::sum()

从结果中可以看出来不能重写用final定义的方法。

在使用final时,只能用来修饰类或者方法,不能修饰属性。当一个类被final修饰后,类中的方法就不需要被final修饰,因为类都不能继承了,方法就不能重写。同时final修饰的类是可以被实例化的。

如果一个方法被final修饰,是可以被继承的,但是不能被重写。

<?php

    class A{
        final public function sum($num1,$num2){
            return $num1 + $num2;
        }

    }

    class B extends A{

    }

    $b = new B();
    echo $b -> sum(1,2);
    .......结果.......
    3

在我们写单例模式时,说过当时的单例模式是不完善的,可以通过继承来得到不同的对象,在这里我们使用final关键字修饰单例类,防止继承,这样就不能通过继承的到别的对象。

类常量

类常量和普通的常量是一个概念,当不希望一个成员变量被修改,希望该变量的值是固定不变的。这时可以用const去修饰该成员变量,这样这个变量就自动成为常量。在类中的常量称为类常量。前面我们讲过定义常量有两种方式define()和关键字const,在类中必须使用const这种方式,使用define()是会报错的。

<?php

    class A{
        const PI = 3.1415926;

        public function getPI(){
            return A::PI;
        }
    }

    $a = new A();
    echo $a -> getPI();
    echo &#39;<br>&#39;;
    echo A::PI;
    ......结果......
    3.1415926
    3.1415926

类常量的命名一般是全部用大写字母,中间用下划线隔开,同时常量前面没有$符号。常量必须在定义的时候就赋值。同时常量的前面不能有修饰符,默认是public。

常量的访问形式

常量的访问形式分为两种,一种是在类的内部进行访问,一种是在类的外部进行访问。

内部访问

通过 类名::常量名进行访问。

class A{
    const PI = 3.1415926;

    public function getPI(){
        return A::PI;//通过类名进行访问
    }
}

通过 self::常量名进行访问

class A{
    const PI = 3.1415926;

    public function getPI(){
        return self::PI;//通过类名进行访问
    }
}

可以通过self进行访问说明常量是属于类的,并不属于对象的。

外部访问

通过类名::常量名访问。

echo A::PI;

通过对象名::常量名访问

$a = new A();
echo $a::PI;

不过推荐使用第一种,通过类名进行访问。

如果一个类中有常量,则在继承的时候常量也是可以被继承的。同时常量的数据类型不能是对象。

总结

PHP中抽象和接口应用让我们的更加清楚的把握需求的骨架,更好的搭建我们的代码体系。同时利用抽象和接口降低代码的耦合度。利于代码的扩展。

 以上就是PHP基础教程十二之抽象、接口的内容,更多相关内容请关注PHP中文网(www.php.cn)!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn