今天來分享賦值、class的一些方法,static等等。
像是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
獲取靜態成員時,使用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方法
能用靜態則用靜態,可略過實體化,達到節省記憶體空間。
當我們需要改變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