php static靜態方法中的「靜態」指的是無需對類進行範例化,就可以直接呼叫這些屬性和方法;而static就是一個關鍵字,用來修飾類的屬性及方法,其使用語法如「class Foo {public static $my_static = 'hello';}」。
php入門到就業線上直播課:進入學習
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API偵錯工具:
本教學操作環境:windows7系統、PHP8.1版、Dell G3電腦。
PHP static靜態詳解
PHP 類屬性和方法都需要在類範例化後才能呼叫(常數屬性除外),但是,PHP 還提供了靜態屬性和靜態方法,所謂「靜態」指的是無需對類進行範例化,就可以直接呼叫這些屬性和方法。靜態類不是不可以範例化,而是不需要範例化就可以用。
用static關鍵字來修飾類的屬性、方法,稱這些屬性、方法為靜態屬性、靜態方法。
語法:
static 屬性名
登入後複製
範例:
<?php
class Foo {
public static $my_static = 'hello';
}
?>
登入後複製
語法:
static function 方法名{
//程式碼
}
登入後複製
範例:
<?php
class Foo {
public static function staticValue() {
return 'hello';
}
}
?>
登入後複製
注:靜態屬性和方法與物件屬性和方法一樣,支援設定 private
、protected
、public
三種可見性級別。
通過 類名::屬性/方法
的方式呼叫。
<?php
class Mystatic {
public static $staticvalue = 'zhangsan';
public static function staticMethod() {
$a = 'hello';
return $a;
}
}
echo '$staticvalue: '.Mystatic::$staticvalue.PHP_EOL;
echo '$a: '.Mystatic::staticMethod().PHP_EOL;
?>
登入後複製
注:預定義常數 PHP_EOL
表示系統換行符。
結果:
$staticvalue: zhangsan
$a: hello
登入後複製
登入後複製
登入後複製
通過 物件名::屬性/方法
的方式呼叫。
<?php
class Mystatic {
public static $staticvalue = 'zhangsan';
public static function staticMethod() {
$a = 'hello';
return $a;
}
}
$obj = new Mystatic();
echo '$staticvalue: '.$obj::$staticvalue.PHP_EOL;
echo '$a: '.$obj::staticMethod();
?>
登入後複製
結果:
$staticvalue: zhangsan
$a: hello
登入後複製
登入後複製
登入後複製
通過物件名 -> 方法
呼叫、物件名 -> 屬性
會失敗。
<?php
error_reporting(0);
class Mystatic {
public static $staticvalue = 'zhangsan';
public static function staticMethod() {
$a = 'hello';
return $a;
}
}
$obj = new Mystatic();
echo '$staticvalue: '.$obj -> staticvalue.PHP_EOL;
echo '$a: '.$obj -> staticMethod();
?>
登入後複製
結果:
$staticvalue:
$a: hello
登入後複製
通過 self::屬性/方法
的方式呼叫,self 指向當前類,就像 $this 指向當前物件一樣;而在沒有範例化的情況下,$this
指標指向的是空物件,所以不能動過它參照靜態屬性和方法。
<?php
class Mystatic {
public static $staticvalue = 'zhangsan';
public static function staticMethod() {
$a = 'hello';
return $a;
}
public function noStatic(){
echo '$staticvalue: '.self::$staticvalue.PHP_EOL;
echo '$a: '.self::staticMethod();
}
}
$obj = new Mystatic();
$obj -> noStatic();
?>
登入後複製
結果:
$staticvalue: zhangsan
$a: hello
登入後複製
登入後複製
登入後複製
與在非靜態方法中呼叫靜態屬性/方法一樣。
<?php
class Mystatic {
public static $staticvalue = 'zhangsan';
public static function staticMethod1() {
$a = 'hello';
return $a;
}
public static function staticMethod2(){
echo '$staticvalue: '.self::$staticvalue.PHP_EOL;
echo '$a: '.self::staticMethod1().PHP_EOL;
}
}
Mystatic::staticMethod2();
$obj = new Mystatic();
$obj -> staticMethod2();
?>
登入後複製
結果:
$staticvalue: zhangsan
$a: hello
$staticvalue: zhangsan
$a: hello
登入後複製
如果在一個類中呼叫其他類的靜態屬性和方法,需要通過 完整類名::
進行參照。
<?php
class Mystatic1 {
public static $staticvalue1 = 'xiaomin';
}
class Mystatic2 {
public static $staticvalue2 = 'zhangsan';
public static function staticMethod() {
echo '$staticvalue1: '.Mystatic1::$staticvalue1.PHP_EOL;
echo '$staticvalue2: '.self::$staticvalue2.PHP_EOL;
}
}
Mystatic2::staticMethod();
$obj = new Mystatic2();
$obj -> staticMethod();
?>
登入後複製
結果:
$staticvalue1: xiaomin
$staticvalue2: zhangsan
$staticvalue1: xiaomin
$staticvalue2: zhangsan
登入後複製
private
、protected
可見性級別的靜態屬性/方法由於private
、protected
屬性的限制只在類內呼叫,想在類外呼叫,需為外部提供一個public
的方法,方法存取private
、protected
屬性。術語:類對外提供介面。
<?php
class Mystatic {
public static $staticvalue1 = 'zhangsan';
private static $staticvalue2 = 20;
protected static $staticvalue3 = 'student';
private static function staticMethod() {
$a = 'hello';
return $a;
}
public function port1() {
echo '$staticvalue1: '.self::$staticvalue1.PHP_EOL;
echo '$staticvalue2: '.self::$staticvalue2.PHP_EOL;
echo '$staticvalue3: '.self::$staticvalue3.PHP_EOL;
echo '$a: '.self::staticMethod().PHP_EOL;
}
public static function port2() {
echo '$staticvalue1: '.self::$staticvalue1.PHP_EOL;
echo '$staticvalue2: '.self::$staticvalue2.PHP_EOL;
echo '$staticvalue3: '.self::$staticvalue3.PHP_EOL;
echo '$a: '.self::staticMethod().PHP_EOL;
}
}
$obj = new Mystatic();
$obj -> port1();
echo "\r\n";
Mystatic::port2();
?>
登入後複製
結果:
$staticvalue1: zhangsan
$staticvalue2: 20
$staticvalue3: student
$a: hello
$staticvalue1: zhangsan
$staticvalue2: 20
$staticvalue3: student
$a: hello
登入後複製
在實際應用中會有一個類的多個物件,可能會共用一份資料。類常數和靜態屬性都可以實現。靜態屬性與類常數相似(相同),唯一的區分是類常數不可以更改,靜態屬性可以更改。存取方法是一樣的,都可以使用::
存取。 靜態屬性需要加$,常數名前沒有$,所以存取類常數時根本不需要加。
<?php
class Myconst {
const A = 1234;
}
$obj1 = new Myconst();
echo 'A: '.$obj1::A.PHP_EOL;
$obj1->A='aaa';
//$obj1::A='aaa';會報錯
echo "\r\n";
$obj2 = new Myconst();
echo 'A: '.$obj2::A.PHP_EOL;
?>
登入後複製
結果:
A: 1234
A: 1234
登入後複製
<?php
class Mystatic {
public static $A = 1234;
}
echo '$A: '.Mystatic::$A.PHP_EOL;
Mystatic::$A = 6666;
echo '$A: '.Mystatic::$A.PHP_EOL;
$obj1 = new Mystatic();
echo '$A: '.$obj1::$A.PHP_EOL;
Mystatic::$A = 5555;
$obj2 = new Mystatic();
echo '$A: '.$obj2::$A.PHP_EOL;
echo '$A: '.$obj1::$A.PHP_EOL;
?>
登入後複製
結果:
$A: 1234
$A: 6666
$A: 6666
$A: 5555
$A: 5555
登入後複製
和非靜態屬性/方法一樣,靜態屬性和方法也可以被子類繼承,靜態屬性和方法還可以被子類重寫。
子類可以重寫父類別的靜態成員變數, 但父類別的靜態變數依然存在, 這兩個靜態成員變數是獨立的. 會根據呼叫的類名分別進行存取。
<?php
class Mystatic
{
static public $a; //定義一個靜態變數
static function test() //定義靜態方法來操作並輸出靜態變數
{
self::$a++;
return self::$a;
}
}
class Mystatic2 extends Mystatic //定義一個子類
{
static function test() //定義子類的靜態方法
{
self::$a++; //存取並操作父類別的靜態變數
return self::$a;
}
}
$obj1=new Mystatic; //新建父類別物件
echo '此時$a的值為: '.$obj1->test().PHP_EOL; //通過物件呼叫靜態方法test,靜態屬性$a的值+1
$obj2=new Mystatic; //新建另一個父類別物件
echo '此時$a的值為: '.$obj2->test().PHP_EOL; //新父類別物件呼叫靜態方法test,靜態屬性$a的值+1+1
$obj3=new Mystatic2; //新建子類物件
echo '此時$a的值為: '.$obj3->test().PHP_EOL; //子類物件呼叫同名靜態方法test, 靜態屬性$a的值+1+1+1
echo Mystatic::$a.PHP_EOL; //通過父類別::直接存取靜態成員$a變數
echo $obj1::$a.PHP_EOL; //通過物件名::可以直接存取靜態成員$a變數
?>
登入後複製
結果:
此時$a的值為: 1
此時$a的值為: 2
此時$a的值為: 3
3
3
登入後複製
子類可以重寫父類別的靜態方法。
<?php
class Mystatic1 {
public static function getclassName() {
return __CLASS__;
}
public static function whoclassName() {
echo self::getclassName().PHP_EOL;
}
}
class Mystatic2 extends Mystatic1{
public static function getclassName() {
return __CLASS__;
}
}
echo Mystatic1::getclassName().PHP_EOL;
echo Mystatic2::getclassName().PHP_EOL;
?>
登入後複製
通過 __CLASS__
可以獲取當前類的類名,我們分別呼叫兩個類的 getClassName
方法:
結果:
Mystatic1
Mystatic2
登入後複製
登入後複製
說明子類重寫了父類別的同名靜態方法,同樣我們在子類上也可以呼叫父類別中的 whoclassName
方法:
<?php
class Mystatic1 {
public static function getclassName() {
return __CLASS__;
}
public static function whoclassName() {
echo self::getclassName().PHP_EOL;
}
}
class Mystatic2 extends Mystatic1{
public static function getclassName() {
return __CLASS__;
}
}
echo Mystatic1::whoclassName();
echo Mystatic2::whoclassName();
?>
登入後複製
結果:
Mystatic1
Mystatic1
登入後複製
為什麼第二個列印的結果是父類別名 Mystatic1
而不是子類名 Mystatic2
?這是因為, $this
指標始終指向持有它的參照物件,而self
指向的是定義時持有它的類
而不是呼叫時的類
,為了解決這個問題,從 PHP 5.3 開始,新增了一個叫做延遲靜態繫結的特性。
延遲靜態繫結(Late Static Bindings)針對的是靜態方法的呼叫,使用該特性時不再通過 self::
參照靜態方法,而是通過 static::
,如果是在定義它的類中呼叫,則指向當前類
,此時和 self
功能一樣,如果是在子類或者其他類中呼叫,則指向呼叫該方法所在的類
。
<?php
class Mystatic1 {
public static function getclassName() {
return __CLASS__;
}
public static function whoclassName() {
echo static::getclassName().PHP_EOL;
}
}
class Mystatic2 extends Mystatic1{
//self改為static
public static function getclassName() {
return __CLASS__;
}
}
echo Mystatic1::whoclassName();
echo Mystatic2::whoclassName();
?>
登入後複製
結果:
Mystatic1
Mystatic2
登入後複製
登入後複製
表明後期靜態繫結生效,即 static
指向的是呼叫它的方法所在的類,而不是定義時,所以稱之為延遲靜態繫結。
此外,還可以通過 static::class
來指向當前呼叫類的類名,例如我們可以通過它來替代 __CLASS__
,這樣上述子類就沒有必要重寫 getClassName
方法了:
<?php
class Mystatic1 {
public static function getclassName() {
return static::class;
}
public static function whoclassName() {
echo static::getclassName().PHP_EOL;
}
}
class Mystatic2 extends Mystatic1{}
echo Mystatic1::getclassName().PHP_EOL;
echo Mystatic2::getclassName().PHP_EOL;
echo Mystatic1::whoclassName();
echo Mystatic2::whoclassName();
?>
登入後複製
結果:
Mystatic1
Mystatic2
Mystatic1
Mystatic2
登入後複製
同理,self::class
則始終指向的是定義它的類。
靜態屬性和方法可以直接通過類參照,所以又被稱作類屬性和類方法。非靜態屬性和非靜態方法需要範例化後通過物件參照,因此被稱作物件屬性和物件方法。
靜態屬性儲存在類空間,非靜態屬性儲存在物件空間。非靜態方法可以存取類中的任何成員(包括靜態),靜態方法只能存取類中的靜態成員。
靜態方法可以直接呼叫,類名呼叫和物件呼叫(類名或self::
呼叫),但是非靜態方法只能通過物件呼叫(物件名或$this->
呼叫)。
一個類的所有範例物件,共用類中的靜態屬性。如果修改了這個類靜態屬性,那麼這個類的所有物件都能存取到這個新值。
靜態方法和屬性的生命週期跟相應的類一樣長,靜態方法和靜態屬性會隨著類的定義而被分配和裝載入記憶體中。一直到執行緒結束,靜態屬性和方法才會被銷燬。 非靜態方法和屬性的生命週期和類的範例化物件一樣長,只有當類範例化了一個物件,非靜態方法和屬性才會被建立,而當這個物件被銷燬時,非靜態方法也馬上被銷燬。靜態方法和靜態變數建立後始終使用同一塊記憶體,而使用範例的方式會建立多個記憶體。但靜態方法效率上要比範例化高,靜態方法的缺點是不自動進行銷燬,而範例化的則可以做銷燬。
靜態方法最適合工具類中方法的定義;比如檔案操作,日期處理方法等.
靜態變數適合全域性變數的定義.
推薦學習:《》
以上就是php的static靜態方法是什麼的詳細內容,更多請關注TW511.COM其它相關文章!