iT邦幫忙

1

PHP 自學筆記 (3)

今天來分享賦值、class的一些方法,static等等。

賦值by reference:

像是js的賦值就都是by reference,也就是當你去複製一個物件,而當其物件改變,會影響到原本的物件。
而我們要達到by value的效果,可以利用clone去複製物件

<?php
class Jojo
{
}

$a = new Jojo();
// 將值物件的變數,賦予給其他變數
$b = $a;
// var_dump($a, $b); // object(Jojo)#1 (0) { } object(Jojo)#1 (0) { }
$a->name = "big";
$b->age = 22;
var_dump($a, $b);
// 可發現修改的為同一個物件,因為物件為by reference
//object(Jojo)#1 (2) { ["name"]=> string(3) "big" ["age"]=> int(22) } 
//object(Jojo)#1 (2) { ["name"]=> string(3) "big" ["age"]=> int(22) }

// 實現by value不影響彼此。
// 可發現兩個物件已經互不影響。
$a = clone $b;
$a->ab = 85;
$b->abc = 87;
var_dump($a, $b);
// object(Jojo)#2 (2) { ["name"]=> string(3) "big" ["age"]=> int(22) ["ab"]=> int(85)} 
// object(Jojo)#1 (3) { ["name"]=> string(3) "big" ["age"]=> int(22) ["abc"]=> int(87) }

範圍解析運算子(::):

透過::範圍解析運算符,從外部獲取class常數。


class Jojo
{
    const PI = 3.14;
}
$a = new Jojo;
// echo $a->PI; // 無法獲取
echo Jojo::PI; //3.14

static:

獲取靜態成員時,使用class名 + 範圍解析操作符(::) + static(屬性名 or 方法)


class Car
{

    // 屬性
    public $feature = "normal";
    // 普通方法
    public function normal()
    {
        echo __FUNCTION__;
    }
    // 靜態屬性
    public static $wheel = 4;
    private static $oil = "full";
    // 靜態方法
    public static function  move()
    {
        echo Car::$oil, __FUNCTION__, "<br/>";
        // 在class中,使用$this內部物件,會報錯,不可在static使用$this
        // $this->move(); // Using $this when not in object context 
    }
}

利用普通方法獲取,並物件實體化,可發現只有獲取到普通屬性,獲取不到靜態屬性,因為靜態屬性屬於class,物件在實體化,並不會將靜態屬性引入。

而利用靜態的方法去獲取,可以獲取class自身屬性且無須物件實體化


// 普通屬性獲取
$a = new Car();
echo $a->feature . "<br/>";
var_dump($a); // object(Car)#1 (1) { ["feature"]=> string(6) "normal" }
echo "<br/>";

// 靜態屬性獲取
echo Car::$wheel . "<br/>";
// 呼叫靜態方法
Car::move();

// 由於靜態方法也都是class所定義的方法,所以也可藉由物件來獲取,但不建議
// $a->move();

// 而普通方法在class內部,編譯時就存在,我們也可透過class來獲取,但不建議(會報錯)
// Car::normal(); // Deprecated: Non-static method Car::normal() should not be called statically

總結:
靜態成員是給class獲取,跟obj是毫無關係,而非靜態成員是給obj獲取
class可以獲取普通方法(但不可帶this),而obj可以無條件獲取static方法
能用靜態則用靜態,可略過實體化,達到節省記憶體空間。

self:

當我們需要改變className,那我們所有的對應的className都需要改變,維護上較費時,所以我們能使用self來替代直接寫className的方法。注意self只能在class內部使用


class Jojo
{
    // 屬性
    private static $count = 0;
    // 方法
    public static function showClass()
    {
        echo Jojo::$count;
        echo "<br/>";
        echo self::$count; // 可以利用self代替className 
    }
}
Jojo::showClass(); // 0

當建構式為public,我們透過物件實體化就會自動呼叫,但當建構式其為private,那麼我們直接透過物件實體化就會報錯,因為為private無法在class外呼叫

如果我們不透過實體化物件,無法獲取class內部,但現在有static,我們可以直接透過靜態的方法,因為他可不透過物件,直接獲取class。而在哪裡new不受影響,前提是要有其class,不管在外面在裡面都可以進行實體化


class Eva
{
    // 設置一個private的建構式
    private function __construct()
    {
        echo __FUNCTION__;
    }
    // 設置一個靜態的function
    public static function getInstance()
    {
        // 在被呼叫後我們在進行物件實體化
        // 而在實體化後,就會呼叫建構式(由於都在內部所以可呼叫)
        // return new Eva();
        return new self();
    }
}

// $a = new Eva;
// Fatal error: Uncaught Error: Call to private Eva::__construct() from invalid context

// 獲取物件(透過靜態,可不用先實體化就可呼叫class內部方法)
$a = Eva::getInstance(); //__construct


尚未有邦友留言

立即登入留言