1. 程式人生 > >PHP面向對象編程高級

PHP面向對象編程高級

形參 機制 log 解決 擴展 重名 alt ret value

1、OOP(Object-Oriented Programming )概述

面向對象的編程特點:代碼更簡潔、更易於維護,並且具有更強的可重用性。
軟件工程的三個目標:重用性、靈活性、擴展性
面向對象編程三大特性:封裝、繼承、多態(PHP不支持)

2、封裝

封裝是從對象抽象成類的過程,其將數據和數據的操作捆綁在一起,形成對外界的隱蔽,同時對外提供可以操作的接口

3、繼承

繼承是類的細分過程,是代碼復用的一大手段

繼承的基礎:子類(要繼承其他類的類,派生類)和父類(被繼承的類,基類)之間是一種被包含和包含的關系,類似人類(對應子類)和動物類(對應父類)的關系

繼承關鍵字:extends

class
Human{} class Man extends Human{}

繼承的效果:父類中大多數屬性和方法在子類中可以直接訪問

有限繼承:子類可以繼承父類除私有方法之外的所有成員

在PHP中一個類只能繼承一個父類,想繼承多個類可以嘗試使用鏈式繼承

4、成員重寫Override

子類中定義了與父類重名的成員的行為稱為重寫,重寫後,子類直接訪問重寫後的成員,如果需要訪問父類中重寫前的成員(只包括靜態屬性、靜態方法、類常量和普通方法),可以在子類中使用parent關鍵字代表父類進行訪問parent::成員名稱

重寫方法原則:

a.控制權不能高於父類

b.參數個數和數據類型(php7)必須一致,形參名字可以更改

c.私有方法不能被繼承,故不受重寫規則限制

5、靜態成員綁定

利用static代替靜態綁定self,使用靜態成員的重寫,使得在類內部用來代表本身的關鍵字不是在類編譯時固定好,而是當方法被訪問是動態地選擇來訪者所屬的類

class Human{
    public static $name = ‘Human‘;

    public static function getName(){
        echo self::$name,‘:self:<br>‘;
        echo static::$name,‘:static:<br>‘;
    }
}
class Man extends Human{ public static $name = ‘Man‘; } Man::getName(); /* *結果 *Human:self: *Man:static: */

靜態延遲綁定只有在繼承時才有意義,它是根據調用類的不同而選擇不同的表現

6、繼承終結者:Final關鍵字解說

final關鍵字只能修飾類和方法,不能用來修飾屬性和類常量

最終類:使用final關鍵字修飾的類即為最終類:final class ClassName{},最終類無法被繼承

final修飾方法時,該方法能被繼承但不能重寫

7、抽象類和抽象方法:Abstract關鍵字解說

使用abstract修飾的類和方法稱為抽象類和抽象方法

抽象類不能實例化,只能被繼承,

抽象方法只能存在於抽象類或接口中,抽象方法不能有方法體,

繼承抽象類的非抽象子類必須實現抽象類中的所有抽象方法,故抽象方法不能使用private修飾

//定義抽象類
abstract class Human{
    //聲明抽象方法
    abstract function display();
    //聲明普通方法
    function fn(){
        echo __MATHOD__.‘<br>‘;
    }
}

class Man extends Human{
    //重寫抽象方法
    function display(){
        echo ‘Man‘;
    }
    //普通方法不必重寫
}

8、接口Interface

接口是類似類的一種結構,使用interface來聲明:interface InterfaceName{}

接口不能被實例化,只能被類實現,使用implements關鍵字:class ClassName implements InterfaceName{}

接口成員:只能定義抽象方法和接口常量

//聲明接口
interface Human{
    //定義接口常量
    const Name = ‘人‘;
    //定義抽象方法,默認是抽象方法,不能使用abstract關鍵字修飾
    public function eat();
}
//實現接口
class Man implements Human{
    //實現抽象方法
    public function eat(){
        echo ‘男人在吃東西<br>‘;
    }
}

抽象類實現接口時不必實現抽象方法

接口的抽象方法必須使用public修飾

實現接口的類不允許重寫接口常量,不允許增加方法控制權限,接口可以多繼承接口,依然是使用extends關鍵字

interface Ship{}
interface Aerocraft{}
interface Airship extends Ship,Aerocraft{}

9、解決單繼承問題的代碼復用機制trait

trait也是一種類似class的關鍵字:trait TraitName{}

trait中可以擁有類中除常量外的其他所有成員,包括抽象方法,trait不能被實例化和繼承

在類中使用trait代碼需要使用use關鍵字:class ClassName{ use TraitName;}

在類中use了具體類時,相當於trait中的代碼在類中寫了一遍。

一個類中可以使用多個trait

trait t1{
    function f1(){
        echo "string";
    }
}
trait t2{
    function f2(){}
}
class C{
    use t1,t2;
    function f3(){
        $this->f1();
        $this->f2();
    }
}

使用的多個trait中成員重名時

trait t1{
    function f1(){
        echo "string";
    }
}
trait t2{
    function f1(){}
}
class C{
    use t1,t2{
        t2::f1 insteadof t1;    //表示f1引用的t2中的f1
        t2::f1 as f2;            //重命名t2中的f1為f2,不寫這句則t2::f1無法被使用
    }
    function f3(){
        $this->f1();
        $this->f2();
    }
}

類中不允許屬性和trait中的屬性同名,方法同名時,類中的方法會覆蓋trait中的同名方法,trait中的方法會覆蓋繼承來的同名方法。

允許類使用別名的方式放松方法訪問控制權

trait t1{
    private function f1(){
        echo "string";
    }
}
class C{
    use t1{
        f1 as public f2;
    }
}
$c = new C();
$c->f2();

10、魔術方法

PHP所提供的"重載"(overloading)是指動態地"創建"類屬性和方法,是通過魔術方法來實現的。
當調用當前環境下未定義或不可見的類屬性或方法時,重載方法會被調用。(屏蔽錯誤)
所有的重載方法都必須被聲明為 public。
屬性重載只能在對象中進行。在靜態方式中,這些魔術方法將不會被調用。所以這些方法都不能被 聲明為 static。
這些魔術方法的參數都不能通過引用傳遞。
---------------------

php重載的內容引用了:
作者:和尚周
來源:CSDN
原文:https://blog.csdn.net/csdn_heshangzhou/article/details/80990687

__construct 構造方法
__destruct 析構方法

__clone 克隆方法

__toString

實現該函數可在echo一個對象時顯示一個提示 function __toString(){ return $tipstrmsg;}

__call
實現該方法後調用類中不存在的方法時,顯示調用不存在信息 function __call($i,$j){ //$i接收方法名,$j接收參數數組}

__callStatic()
描述:用靜態方式中調用一個不可訪問方法時,__callStatic() 會被調用。public static function __callStatic ( string $name , array $arguments )

__get
訪問類中無權訪問的成員時調用該方法提示信息 function __get($i){ //$i訪問的成員}

__set
設置類中無權設置的成員時調用該方法提示信息 function __set($i,$j){ //$i要設置的成員,$j要設置的值}

__isset
查看類中無權查看的成員 function __isset($i){echo "您無權查看{$i}是否存在!";}

__unset
刪除類中無權刪除的成員 function __unset($i){echo "您無權刪除{$i}!";}

測試代碼:

class ClassName{
    private $a = 1;
    private function pri(){}
    public static function s(){}

    public function __get($var){
        echo "<br>Error:屬性{$var}無法訪問!<br>";
    }

    public function __set($var,$value){
        echo "<br>Error:無權設置屬性{$var}的值!<br>";
    }

    public function __isset($var){
        echo "<br>Error:您無權查看{$var}是否存在!<br>";
    }

    public function __unset($var){
        echo "<br>Error:您無權刪除{$var}!<br>";
    }

    public function __call($func,$args){
        echo "<br>Error:方法{__MATHOD__}不可訪問!<br>";
    }

    public static function __callStatic($func,$args){
        echo "<br>Error:靜態方法{__MATHOD__}不可訪問!<br>";
    }

    public function __toString(){
        return ‘object(‘.__CLASS__.‘)‘;
    }
}

$c = new ClassName();
echo $c->a;
$c->a = 3;
isset($c->a);
unset($c->a);
$c->pri();
$c->s();
echo $c;

測試結果:

技術分享圖片

PHP面向對象編程高級