php static靜態方法中的「靜態」指的是不需要對類別進行實例化,就可以直接呼叫這些屬性和方法;而static就是一個關鍵字,用來修飾類別的屬性及方法,其使用語法如「class Foo {public static $my_static = 'hello';}」。
本教學操作環境: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)针对的是静态方法的调用,使用该特性时不再通过 <span style="background-color:#fe2c24;">self::</span>
引用静态方法,而是通过 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视频教程》
以上是php的static靜態方法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!