PHP基礎參考10-類與對象語法


原文:PHP基礎參考10-類與對象語法 - 9ong
PHP基礎參考11-引用語法 - 9ong

很多人都停留在php是過程語言,不能面向對象,php已經8了,在5就已經逐步與面向對象接軌了。

PHP 具有完整的對象模型。特性包括: 訪問控制,抽象類和 final 類與方法,附加的魔術方法,接口,對象復制。

對于面向對象的基本知識,不需要我們介紹了,大家都懂。

PHP: OOP 變更日志 - Manual

final

被繼承的方法和屬性可以通過用同樣的名字重新聲明被覆蓋。但是如果父類定義方法時使用了 final,則該方法不可被覆蓋。可以通過 parent:: 來訪問被覆蓋的方法或屬性。

注意: 屬性不能被定義為 final,只有類和方法才能被定義為 final。

基本的知識,但很少人能用上,也許是場景不需要用到,但也許哪天就真香,時刻牢記。

var

雖然有些版本允許使用var定義屬性,會被視為public,但我們不建議使用。

const常量

常量的值必須是一個定值,不能是變量,類屬性,數學運算的結果或函數調用。

要區別于外部const/define定義的常量。

PHP 7.1.0 開始,類的常量可以定義為公有、私有或受保護。如果沒有設置這些關鍵字,則該常量默認為公有,也就是之前的版本只能使用const關鍵字定義常量,默認這些常量是公開可訪問的,7.1之后允許public、protect、private的訪問控制關鍵字。

類自動加載

現代php框架都引入自動加載機制了,特別是composer第三方庫使用。

spl_autoload_register() 函數可以注冊任意數量的自動加載器,當使用尚未被定義的類(class)和接口(interface)時自動去加載。

不建議使用__autoload函數,后續版本會被棄用。

spl_autoload_register函數用于注冊觸發加載類,提供回調加載,達到按需加載。

spl_autoload_register(function ($class_name) {
    require_once $class_name . '.php';
});

$obj  = new MyClass1();
$obj2 = new MyClass2();

構造函數與析構函數

  • 子類的構造函數不會默認或隱性的調用父類構造函數,有需要時,要手動調用父類構造函數。

  • 析構函數即使在使用 exit() 終止腳本運行時也會被調用。但在析構函數中調用 exit() 將會中止其余關閉操作的運行。

  • 在析構函數(在腳本終止時被調用)中拋出一個異常會導致致命錯誤。

范圍解析操作符

范圍解析操作符 ::

只是認識下這個符號叫:范圍解析操作符

在訪問類常量、靜態屬性、靜態方法,我們常會用到雙冒號,也就是范圍解析操作符。

關于抽象類和接口

如果對抽象類和接口有不清楚的可以看官方文檔介紹

PHP: 抽象類 - Manual

PHP: 對象接口 - Manual

Trait

Trait 是為類似 PHP 的單繼承語言而準備的一種代碼復用機制。Trait 為了減少單繼承語言的限制,使開發人員能夠自由地在不同層次結構內獨立的類中復用 method。

Trait 和 Class 相似,但僅僅旨在用細粒度和一致的方式來組合功能。 無法通過 trait 自身來實例化。它為傳統繼承增加了水平特性的組合;也就是說,應用的幾個 Class 之間不需要繼承。

  • 優先順序是當前類中的方法會覆蓋 trait 方法,而 trait 方法又覆蓋了基類中的方法。

    
    class Base {
        public function sayHello() {
            echo 'Hello ';
        }
    }
    
    trait HelloWorld {
        public function sayHello() {
            echo 'Hello World!';
        }
    }
    
    class MyHelloWorld extends Base {
        use HelloWorld;
    }
    
    
    $o = new MyHelloWorld();
    $o->sayHello();
    //輸出:Hello World!
    //因為trait覆蓋了基類的方法
    
    class TheWorldIsNotEnough {
        use HelloWorld;
        public function sayHello() {
            echo 'Hello Universe!';
        }
    }    
    
    $o = new TheWorldIsNotEnough();
    $o->sayHello();    
    
    //輸出:Hello Universe!
    //因為當前類覆蓋trait的方法
    
  • 一個類中支持use多個trait,用逗號隔開

  • 方法沖突解決

    如果兩個 trait 都插入了一個同名的方法,如果沒有明確解決沖突將會產生一個致命錯誤。

    為了解決多個 trait 在同一個類中的命名沖突,需要使用 insteadof 操作符來明確指定使用沖突方法中的哪一個。

    以上方式僅允許排除掉其它方法,as 操作符可以 為某個方法引入別名。 注意,as 操作符不會對方法進行重命名,也不會影響其方法。

    use A, B {
        B::smallTalk insteadof A;//相當于排除A中的smallTalk
        A::bigTalk insteadof B;
        B::bigTalk as talk;//定義了talk別名
    }
    
  • 修改use trait中的方法訪問控制

    直接看范例:

    
    // 修改 sayHello 的訪問控制
    class MyClass1 {
        use HelloWorld { sayHello as protected; }
    }
    
    // 給方法一個改變了訪問控制的別名
    // 原版 sayHello 的訪問控制則沒有發生變化
    class MyClass2 {
        use HelloWorld { sayHello as private myPrivateHello; }
    }
    
  • trait組合

    trait和class一樣也可以組合其他多個trait。

  • trait支持抽象方法,用于強制實體類實現trait的抽象方法

  • trait支持靜態方法

  • trait支持屬性,但注意沖突,一般是不能定義同樣名稱的屬性。我們建議避免trait和class出現相同名稱的屬性,即使訪問可見性、初始值都一樣(允許的),我也不建議,會導致混亂。

匿名類

php7開始支持匿名類,用于創建一次性簡單對象。

$util->setLogger(new class {
    public function log($msg)
    {
        echo $msg;
    }
});
//也就是不需要先定義一個logger的對象,再new給setLogger方法。

魔術方法

PHP: 魔術方法 - Manual

PHP所提供的重載(overloading)是指動態地創建類屬性和方法。我們是通過魔術方法(magic methods)來實現的。

PHP中的重載與其它絕大多數面向對象語言不同。傳統的重載是用于提供多個同名的類方法,但各方法的參數類型和個數不同。

PHP: 重載 - Manual

clone

對象復制可以通過 clone 關鍵字來完成(如果可能,這將調用對象的 __clone() 方法)。

當對象被復制后,PHP 5 會對對象的所有屬性執行一個淺復制(shallow copy)。所有的引用屬性 仍然會是一個指向原來的變量的引用。如果有少量及簡單的引用屬性,可以在魔術方法__clone中手動實現引用屬性的復制。

class AA{
    public $object1;
    function __clone()
    {
    
        // 強制復制一份this->object, 否則仍然指向同一個對象
        $this->object1 = clone $this->object1;
    }
}

$a = new AA();

$a2 = clone $a;//通過__clone方法,達到對$a對象的深拷貝。

static::后期靜態綁定

self、parent、static

我們都知道parent的用法,就是從當前類(子類)往上追溯基類的存在的這個方法;static則是從當前類(父類、基類)往下追溯至當前執行實例(子類)中存在的方法;

class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // 后期靜態綁定從這里開始,這里會執行調用test方法的實例的who方法,也就是B類實例的who方法。
        self::who();//這里只會調用當前類中的who方法,如果有的話,也就是當前代碼行所在類A
        parent::who();
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();//輸出:BA

對象與引用及傳址賦值與引用賦值

在php5 的對象編程經常提到的一個關鍵點是“默認情況下對象是通過引用傳遞的”。但其實這不是完全正確的。

PHP 的引用是別名,就是兩個不同的變量名字指向相同的內容。

在 PHP 5以后,一個對象變量已經不再保存整個對象的值。而是保存一個標識符來訪問真正的對象內容。

當對象作為參數傳遞,作為結果返回,或者賦值給另外一個變量,另外一個變量跟原來的不是引用的關系,只是他們都保存著同一個標識符的拷貝,這個標識符指向同一個對象的真正內容。

這標識符我們可以理解為存儲地址,所以php的對象正常情況下的復制、傳遞都是通過傳址的方式,而不是引用,雖然效果是一樣的。

class A {
    public $foo = 1;
}  

$a = new A;
$b = $a;     // $a ,$b都是同一個標識符的拷貝,意味著a、b指向同一個地址
            // ($a) = ($b) = <id>
$b->foo = 2;
echo $a->foo."\n";//輸出:2


$c = new A;
$d = &$c;    // $c ,$d是引用,d是c的一個別名,其實他們還是一樣的
            // ($c,$d) = <id>

$d->foo = 2;
echo $c->foo."\n";//輸出:2


$e = new A;

function foo($obj) {//e和obj都是同一個標識符的拷貝
    // ($obj) = ($e) = <id>
    $obj->foo = 2;
}

foo($e);
echo $e->foo."\n";//輸出:2

原文:PHP基礎參考10-類與對象語法 - 9ong
PHP基礎參考11-引用語法 - 9ong

?著作權歸作者所有,轉載或內容合作請聯系作者
禁止轉載,如需轉載請通過簡信或評論聯系作者。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370

推薦閱讀更多精彩內容