很多朋友可能分不清楚在php中靜態(tài)變量與靜態(tài)方法的用法與區(qū)別在哪里,下面我來根據(jù)自己的經(jīng)驗來介紹靜態(tài)變量與靜態(tài)方法一些理解。
在PHP中,靜態(tài)變量的解釋是存在于類作用域的變量,在第一次初始化時給變量賦值,以后類初始化時,靜態(tài)變量將不會再被重新賦值,主要用于一個類具有多個實例時的變量共享.
使用靜態(tài)變量
變量范圍的另一個重要特性是靜態(tài)變量(static variable),靜態(tài)變量僅在局部函數(shù)域中存在,但當程序執(zhí)行離開此作用域時,其值并不丟失,看看下面的例子:
演示需要靜態(tài)變量的例子,代碼如下:
- <?php
- function Test ()
- {
- $a = 0;
- echo $a;
- $a++;
- }
- ?>
本函數(shù)沒什么用處,因為每次調(diào)用時都會將 $a 的值設為 0 并輸出 "0",將變量加一的 $a++ 沒有作用,因為一旦退出本函數(shù)則變量 $a 就不存在了,要寫一個不會丟失本次計數(shù)值的計數(shù)函數(shù),要將變量 $a 定義為靜態(tài)的:
使用靜態(tài)變量的例子,代碼如下:
- <?php
- function Test()
- {
- static $a = 0;
- echo $a;
- $a++;
- }
- ?>
現(xiàn)在,每次調(diào)用 Test() 函數(shù)都會輸出 $a 的值并加一.
靜態(tài)變量也提供了一種處理遞歸函數(shù)的方法。遞歸函數(shù)是一種調(diào)用自己的函數(shù)。寫遞歸函數(shù)時要小心,因為可能會無窮遞歸下去。必須確保有充分的方法來中止遞歸。一下這個簡單的函數(shù)遞歸計數(shù)到 10,使用靜態(tài)變量 $count 來判斷何時停止:
靜態(tài)變量與遞歸函數(shù),代碼如下:
- <?php
- function Test()
- {
- static $count = 0;
- $count++;
- echo $count;
- if ($count < 10) {
- Test ();
- }
- $count--;
- }
- ?>
注:靜態(tài)變量可以按照上面的例子聲明,如果在聲明中用表達式的結(jié)果對其賦值會導致解析錯誤。
聲明靜態(tài)變量,代碼如下:
- <?php
- function foo(){
- static $int = 0; // correct
- static $int = 1+2; // wrong (as it is an expression)
- static $int = sqrt(121); // wrong (as it is an expression too)
- $int++;
- echo $int;
- }
- ?>
靜態(tài)方法,代碼如下:
- <?php
- class Fruit {
- public static $category = "I'm fruit";
- static function find($class)
- {
- $vars = get_class_vars($class) ;
- echo $vars['category'] ;
- }
- }
- class Apple extends Fruit {
- public static $category = "I'm Apple";
- }
- Apple::find("Apple");
- ?>
- //程序運行結(jié)果:1 I'm Apple
Program List:重寫基類方法,在派生類重寫基類的方法,代碼如下:
- <?php
- class Fruit
- {
- static function Foo ( $class = __CLASS__ )
- {
- call_user_func(array($class, 'Color'));
- }
- }
- class Apple extends Fruit
- {
- static function Foo ( $class = __CLASS__ )
- {
- parent::Foo($class);
- }
- static function Color()
- {
- echo "Apple's color is red";
- }
- }
- Apple::Foo(); // This time it works.
- ?>
- //程序運行結(jié)果:Apple's color is red
Program List:靜態(tài)數(shù)組的使用
靜態(tài)和const作用域都可以用::操作符訪問,如果你想使用::操作符訪問數(shù)組,你需要事先將數(shù)組聲明為靜態(tài),代碼如下:
- <?php
- class Fruit
- {
- static $color = array('color1' => 'red', 'color2' => 'yellow');
- }
- class Apple
- {
- public function __construct()
- {
- var_dump(Fruit::$color);
- }
- }
- class Banana
- {
- public function __construct()
- {
- Fruit::$color = FALSE;
- }
- }
- new Apple(); // prints array(2) { ["color1"]=> string(3) "red" ["color2"]=> string(6) "yellow" }
- echo '<br />';
- new Banana();
- new Apple(); // prints bool(false)
- ?>
Program List:再來一個單例模式,Static真的很酷,下面的程序演示了如何獲得一個已經(jīng)存在的實例,代碼如下:
- <?php
- class Singleton {
- private static $instance=null;
- private $value=null;
- private function __construct($value) {
- $this->value = $value;
- }
- public static function getInstance() {
- if ( self::$instance == null ) {
- echo "<br>new<br>";
- self::$instance = new Singleton("values");
- }
- else {
- echo "<br>old<br>";
- }
- return self::$instance;
- }
- }
- $x = Singleton::getInstance();
- var_dump($x); // returns the new object
- $y = Singleton::getInstance();
- var_dump($y); // returns the existing object
- ?>
例,靜態(tài)變量與靜態(tài)方法,代碼如下:
- class A {
- static $i = 10;
- public function set($n)
- {
- self::$i = $n;
- }
- public function get()
- {
- return self::$i;
- }
- }
- $a = new A();
- $a->set(11);
- $a1= new A();
- echo $a1->get();
輸出結(jié)果為11,可以看到類A在第二次實例化后,靜態(tài)變量$i依然與上一次實例化時后設定的$i值是一致的,用java來解釋,其實就是一個類的靜態(tài)變量在多個實例中都使用了一個內(nèi)存空間,我覺得這樣解釋更加便于理解,因為靜態(tài)變量和靜態(tài)方法不需要實例化就可以使用,因而在文件被加載后靜態(tài)變量就會初始化,而靜態(tài)方法則會被注冊。這也就可以理解,為什么java類的入口會這樣的了,代碼如下:
public static void main(String[] args){}
我以前一直覺得由于靜態(tài)方法不需要實例化就可以直接使用,節(jié)約了實例化的巨大開銷,因而在使用一個類的方法時我更加傾向于直接靜態(tài)調(diào)用而避免實例化。對于這個問題,我與同事已經(jīng)爭論過很多次,他不主張靜態(tài)調(diào)用主要有以下想法:
1.實例化類更加符合面向?qū)ο缶幊痰乃枷耄?/p>
2.靜態(tài)調(diào)用方法并不能在消耗上有較大的節(jié)約。
對于這個問題,我還是堅持自己的觀點,但也并不是無論什么時候都使用靜態(tài)調(diào)用,我主要有以下想法:
1.由于靜態(tài)變量在文件被載入時就會被初始化,因此如果有多個類,并且類中存在多個靜態(tài)變量與方法,勢必在還未實例化時已消耗較多的內(nèi)存(未驗證),所以對于訪問不頻繁或特殊需要,不建議將一個方法設為static;
2.對于調(diào)用較為頻繁的類,我強烈建設使用static靜態(tài)和靜態(tài)方法,不僅可以共享內(nèi)存空間,還可以共享數(shù)據(jù)。細心就會發(fā)現(xiàn)目前主流的PHP框架的基類都是使用的靜態(tài)調(diào)用方法。
新聞熱點
疑難解答