AI:please wait…
在PHP中,静态方法(Static methods)与普通方法(Instance methods)有以下不同:
-
调用方式:静态方法可以通过类名直接调用,而普通方法需要通过类的实例对象调用。
示例:class MyClass { public static function staticMethod() { echo "This is a static method."; } public function instanceMethod() { echo "This is an instance method."; } } MyClass::staticMethod(); // 调用静态方法 $obj = new MyClass(); $obj->instanceMethod(); // 调用普通方法
-
访问权限:静态方法可以访问和修改静态属性(Static properties),而普通方法可以访问和修改实例属性(Instance properties)。
示例:class MyClass { public static $staticProperty = "Static Property"; public $instanceProperty = "Instance Property"; public static function staticMethod() { echo self::$staticProperty; } public function instanceMethod() { echo $this->instanceProperty; } } MyClass::staticMethod(); // 输出 "Static Property" $obj = new MyClass(); $obj->instanceMethod(); // 输出 "Instance Property"
-
继承:静态方法可以被继承并覆盖(Override),而普通方法也可以被继承并覆盖。
示例:class ParentClass { public static function staticMethod() { echo "This is the parent's static method."; } public function instanceMethod() { echo "This is the parent's instance method."; } } class ChildClass extends ParentClass { public static function staticMethod() { echo "This is the child's static method."; } public function instanceMethod() { echo "This is the child's instance method."; } } ParentClass::staticMethod(); // 输出 "This is the parent's static method." ChildClass::staticMethod(); // 输出 "This is the child's static method." $parentObj = new ParentClass(); $parentObj->instanceMethod(); // 输出 "This is the parent's instance method." $childObj = new ChildClass(); $childObj->instanceMethod(); // 输出 "This is the child's instance method."
https://www.php.net/manual/zh/language.oop5.static.php
声明类属性或方法为静态,就可以不实例化类而直接访问。
静态方法
<?php
/**
* 静态(static)关键字
*
* 声明类属性或方法为静态,就可以不实例化类而直接访问。
* 静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)
*
* 由于静态方法不需要通过对象即可调用,所以伪变量$this在静态方法中不可用!!
*/
class Foo
{
public static function aStaticMethod()
{
// ...
echo '静态方法调用';
}
}
//两种静态方法的调用方式
Foo::aStaticMethod();
//$classname = 'Foo';
//$classname::aStaticMethod();
静态方法&&静态变量
<?php
/**
* 静态(static)关键字,静态属性
*
* 静态属性不可以由对象通过 -> 操作符来访问。
* 通过变量来引用一个类是可行的,但这个变量的值不能是一个保留字 (例如self,parent和 static)
*/
class Foo
{
public static $my_static = '静态变量:foo';
public function staticValue()
{
return self::$my_static;
}
}
class Bar extends Foo
{
public function fooStatic()
{
return parent::$my_static;
}
}
print Foo::$my_static . "\n"; //直接调用静态变量
//静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
$foo = new Foo();
print $foo->staticValue() . "\n"; //可以访问静态方法
//print $foo->my_static . "\n"; // 会报错的,静态属性不可以由对象通过 -> 操作符来访问。
echo '<br/>';
echo '<br/>';
echo '<br/>';
$foo = new Foo();
print $foo::$my_static . "\n";
$classname = 'Foo';
print $classname::$my_static . "\n";
echo '<br/>';
echo '<br/>';
echo '<br/>';
//Bar是子类访问父类的静态变量
print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";
echo '<br/>';
print $bar->staticValue();
继承会覆盖
<?php
/**
* 继承会覆盖
*/
class A
{
static protected $test = "class a";
public function static_test()
{
echo static::$test; //打印什么?? class b
echo '<br/>';
echo self::$test; //打印什么?? class a
}
}
class B extends A
{
static protected $test = "class b";
}
$obj = new B();
$obj->static_test();
静态成员由类的所有实例共享,尽管类的每个实例都存在一个非静态成员。
<?php
/**
* 也就是说,静态成员由类的所有实例共享,尽管类的每个实例都存在一个非静态成员。
*/
class Base
{
public $a;
public static $b;
}
class Derived extends Base
{
public function __construct()
{
$this->a = 0;
parent::$b = 0;
}
public function f()
{
$this->a++;
parent::$b++;
}
}
$obj1 = new Derived();
$obj2 = new Derived();
$obj3 = new Derived();
$obj1->f();
echo $obj1->a;echo Derived::$b; //11
echo '<br/>';
echo '<br/>';
$obj2->f();
echo $obj2->a;echo Derived::$b; //12
echo '<br/>';
echo '<br/>';
$obj3->f();
echo $obj3->a;echo Derived::$b; //13
要检查类中声明的方法是否是静态的,可以使用以下代码。PHP5有一个反射类,非常有用
<?php
class base
{
public static function test()
{
}
public function test1()
{
}
}
try {
$method = new ReflectionMethod('base::test');
if ($method->isStatic()) {
echo 'yes';
} else {
echo 'no';
}
} catch (ReflectionException $e) {
echo $e->getMessage();
}
修饰全局作用域的变量
<?php
function testStatic()
{
static $val = 1; //修饰全局作用域的变量
echo $val;
$val++;
}
/**
* 在函数执行完后,变量值仍然保存
*/
testStatic(); //echo 1
testStatic(); //echo 2
testStatic(); //echo 3
这里static的作用即类似于C里的static的作用,保证$a变量只有在add()第一次调用时才会被初始化,
但需要注意的是定义static变量的时候,可以不赋初值,可以给定初值,
但是赋初值的时候不能使用表达式或者调用函数赋值,否则会报错。
//www.kegog11.com/admin/demo/test
public function test(){
for($i=0;$i<5;$i++){
static $a = 0;
echo $a,"<br />";
$a++;
}
echo $a,"<br />";
}
//结果集?
static变量不会存储引用(但是可以存储对象),
当static存储引用时,二次调用函数后,该变量的值并未被保存下来,
且运行上面程序会报Deprecated错误,即返回引用值赋值的用法已弃。
<?php
function get_obj_ref(){
static $obj = null;
echo '第一个:Ststic obj:';
var_dump($obj);
echo '<br/>';
if(is_null($obj)){
$obj = &new stdClass();
}
return $obj;
}
$obj = get_obj_ref();
$obj2 = get_obj_ref();
//====================================================
echo '<br/>';
function get_obj_noref(){
static $obj = null;
echo '第二个:Ststic obj:';
var_dump($obj);
echo '<br/>';
if(is_null($obj)){
$obj = new stdClass();
}
return $obj;
}
$obj = get_obj_noref();
$obj2 = get_obj_noref();
static在类中的延迟静态绑定;
/**
* 2:static在类中的延迟静态绑定;
*
* 延迟静态绑定是指允许在一个静态继承的上下文中引用被调用类。
* 延迟绑定的意思为:
* static::不再为定义当前方法所在的类,而是实际运行时所在的类。注:它可以用于(但不限于)静态方法的调用。
*
* 除了简单的static延迟绑定的用法,还有一种转发调用,即使用self::,
* parent::,static:: 以及forward_static_call()(该函数只能在方法中调用)将转发调用信息,如下:
*/
class A
{
public static function foo()
{
static::who();
}
public static function who()
{
echo __CLASS__ . "\n";
}
}
class B extends A
{
public static function test()
{
A::foo();
parent::foo();
self::foo();
}
public static function who()
{
echo __CLASS__ . "\n";
}
}
class C extends B
{
public static function who()
{
echo __CLASS__ . "\n";
}
}
C::test();
//这里得到的结果是A C C,显然在调用parent::foo()时,还是使用了运行时调用类。
还有一点需要注意的是:只有显示声明的static类才是从属与子类的。
<?php
/**
* 还有一点需要注意的是:只有显示声明的static类才是从属与子类的。
*
* 这里得到的结果是 b b。这里B类首先调用过test()方法,调用后$var2变量已经被赋值,
* 而C类未定义自己的$var2变量,且父类中$var2变量值已经存在,
* 故直接使用,若在B C类中显示定义$var2变量,则结果又会有所不同。
*/
class A
{
protected static $var1 = null;
protected static $var2 = null;
public static function test()
{
if (!static::$var2) {
static::$var2 = static::$var1;
}
echo get_called_class() . '===>' . static::$var2 . '<br/>';
}
}
class B extends A
{
protected static $var1 = 'b';
}
class C extends A
{
protected static $var1 = 'c';
}
B::test();
C::test();