很多朋友可能分不清楚在php中静态变量与静态方法的用法与区别在哪里,下面我来根据自己的经验来介绍静态变量与静态方法一些理解。
在PHP中,静态变量的解释是存在于类作用域的变量,在第一次初始化时给变量赋值,以后类初始化时,静态变量将不会再被重新赋值,主要用于一个类具有多个实例时的变量共享.
使用静态变量
变量范围的另一个重要特性是静态变量(static variable),静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失,看看下面的例子:
演示需要静态变量的例子,代码如下:
<?php function Test() { $a = 0; echo $a; $a++; } ?>
本函数没什么用处,因为每次调用时都会将 $a 的值设为 0 并输出 "0",将变量加一的 $a 没有作用,因为一旦退出本函数则变量 $a 就不存在了,要写一个不会丢失本次计数值的计数函数,要将变量 $a 定义为静态的:
使用静态变量的例子,代码如下:
<?php function Test() { static $a = 0; echo $a; $a++; } ?>
现在,每次调用 Test() 函数都会输出 $a 的值并加一.
静态变量也提供了一种处理递归函数的方法。递归函数是一种调用自己的函数。写递归函数时要小心,因为可能会无穷递归下去。必须确保有充分的方法来中止递归。一下这个简单的函数递归计数到 10,使用静态变量 $count 来判断何时停止:
静态变量与递归函数,代码如下:
<?php function Test() { static $count = 0; $count++; echo $count; if ($count < 10) { Test(); } $count--; } ?>
注:静态变量可以按照上面的例子声明,如果在声明中用表达式的结果对其赋值会导致解析错误。
声明静态变量,代码如下:
<?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; } ?>
静态方法,代码如下:
<?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"); //程序运行结果: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. //程序运行结果:Apple's color is red ?>
Program List:静态数组的使用
静态和const作用域都可以用::操作符访问,如果你想使用::操作符访问数组,你需要事先将数组声明为静态,代码如下:
<?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真的很酷,下面的程序演示了如何获得一个已经存在的实例,代码如下:
<?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 ?>
例,静态变量与静态方法,代码如下:
<?php 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(); ?>
输出结果为11,可以看到类A在第二次实例化后,静态变量$i依然与上一次实例化时后设定的$i值是一致的,用java来解释,其实就是一个类的静态变量在多个实例中都使用了一个内存空间,我觉得这样解释更加便于理解,因为静态变量和静态方法不需要实例化就可以使用,因而在文件被加载后静态变量就会初始化,而静态方法则会被注册。这也就可以理解,为什么java类的入口会这样的了,代码如下:
public static void main(String[] args){}
我以前一直觉得由于静态方法不需要实例化就可以直接使用,节约了实例化的巨大开销,因而在使用一个类的方法时我更加倾向于直接静态调用而避免实例化。对于这个问题,我与同事已经争论过很多次,他不主张静态调用主要有以下想法:
1.实例化类更加符合面向对象编程的思想;
2.静态调用方法并不能在消耗上有较大的节约。
对于这个问题,我还是坚持自己的观点,但也并不是无论什么时候都使用静态调用,我主要有以下想法:
1.由于静态变量在文件被载入时就会被初始化,因此如果有多个类,并且类中存在多个静态变量与方法,势必在还未实例化时已消耗较多的内存(未验证),所以对于访问不频繁或特殊需要,不建议将一个方法设为static;
2.对于调用较为频繁的类,我强烈建设使用static静态和静态方法,不仅可以共享内存空间,还可以共享数据。细心就会发现目前主流的PHP框架的基类都是使用的静态调用方法。