php静态方法创建对象,PHP 静态属性和静态方法

PHP 静态属性和静态方法

由 学院君 创建于10个月前, 最后更新于 7个月前

版本号 #2

2048 views

1 likes

0 collects

基本使用

前面介绍的 PHP 类属性和方法都要在类实例化后才能调用(常量属性除外),除此之外,PHP 还提供了静态属性和静态方法,所谓「静态」指的是无需对类进行实例化,就可以直接调用这些属性和方法,这么生讲有点硬,我们举个例子一看就明白了。

静态属性和方法的定义和调用

在 php_learning/oop 目录下新建一个 static.php 文件,编写一段测试代码如下:

class Car

{

public static $WHEELS = 4;

public static function getWheels()

{

return self::$WHEELS;

}

}

在 PHP 中,我们通过 static 关键字来修饰静态属性和方法,这里我们定义了一个静态属性$WHEELS 和静态方法 getWheels,由于静态属性和方法可以直接通过类引用,所以又被称作类属性和类方法(相应的,非静态属性和非静态方法需要实例化后通过对象引用,因此被称作对象属性和对象方法),静态属性和方法可以通过 类名::属性/方法 的方式调用:

echo "WHEELS:" . Car::$WHEELS . PHP_EOL;

echo "getWheels:" . Car::getWheels() . PHP_EOL;

如果是在类内部方法中,需要通过 self:: 引用当前类的静态属性和方法,就像常量一样,因为静态属性和方法无需实例化类即可使用,而没有实例化的情况下,$this 指针指向的是空对象,所以不能动过它引用静态属性和方法:

bdb20542f8e0ffc86704c3a1eece4c7a.png

同理,我们也不能在静态方法中通过 $this 引用对象属性和方法。

静态属性支持动态修改

为了以示区别,这里通过了大写字母设置静态属性变量名,这不是强制的,因为静态属性名和常量不同,可以在运行时进行修改,只是它的作用域是整个类,而不是某个对象:

Car::$WHEELS = 8;

echo "getWheels:" . Car::getWheels() . PHP_EOL;

上述代码的打印结果是:

getWheels:8

并且静态属性和方法与对象属性和方法一样,支持设置 private、protected、public 三种可见性级别。

调用另一个类的静态属性/方法

如果在一个类中调用其他类的静态属性和方法,需要通过 完整类名:: 进行引用:

class Gas

{

public static $POWER = '汽油';

}

class Car

{

protected static $WHEELS = 4;

public static function getWheels()

{

return self::$WHEELS;

}

public static function printCar()

{

printf("这辆车有 %d 个轮子,使用 %s 作为动力来源\n", self::$WHEELS, Gas::$POWER);

}

}

Car::printCar();

这里我们通过 Gas::$POWER 引用了 Gas 中的静态属性 $POWER,静态方法也是类似,上述代码打印结果如下:

d511a1c96e0316fed27a606bcf7516ce.png

在非静态方法中调用静态属性/方法

另外,我们前面提到不能在静态方法中通过 $this 调用非静态属性/方法,但是在非静态方法中可以通过 self:: 调用静态属性/方法:

class Car

{

...

public static function printCar()

{

return sprintf("这辆车有 %d 个轮子,使用 %s 作为动力来源\n", self::$WHEELS, Gas::$POWER);

}

public function __toString()

{

return self::printCar();

}

}

$car = new Car();

echo $car;

这很好理解,因为前者是因为没有实例化就可以调用,后者实例化后不影响类方法的调用,在上述代码中,我们将静态方法 printCar 调整为通过 sprintf 函数返回格式化字符串,然后在魔术方法 __toString 方法中调用,作为该非静态方法的返回值。上述代码的打印结果是:

45de6a4624b7dc66b42f31bc437e5ed1.png

完全可以正常运行。

进阶功能

静态方法的继承和重写

和非静态属性/方法一样,静态属性和方法也可以被子类继承,静态方法还可以被子类重写:

class Car

{

...

public static function getClassName()

{

return __CLASS__;

}

public static function who()

{

echo self::getClassName() . PHP_EOL;

}

}

class LynkCo01 extends Car

{

public static function getClassName()

{

return __CLASS__;

}

}

通过 __CLASS__ 可以获取当前类的类名,我们分别调用两个类的 getClassName 方法:

echo Car::getClassName() . PHP_EOL;

echo LynkCo01::getClassName() . PHP_EOL;

打印结果如下:

8981a34b24fde5997ee83227ec0d842d.png

说明子类重写了父类的同名静态方法,同样我们在子类上也可以调用父类中的 who 方法:

Car::who();

LynkCo01::who();

上述代码的打印结果是:

Car

Car

咦?为什么第二个打印的结果是父类名 Car 而不是子类名 LynkCo01?这是因为,和 $this 指针始终指向持有它的引用对象不同,self 指向的是定义时持有它的类而不是调用时的,为了解决这个问题,从 PHP 5.3 开始,新增了一个叫做后期静态绑定的特性。

后期静态绑定

后期静态绑定(Late Static Bindings)针对的是静态方法的调用,使用该特性时不再通过 self:: 引用静态方法,而是通过 static::,如果是在定义它的类中调用,则指向当前类,此时和 self 功能一样,如果是在子类或者其他类中调用,则指向调用该方法所在的类,我们通过后期静态绑定改写上述代码:

class Car

{

...

public static function getClassName()

{

return __CLASS__;

}

public static function who()

{

echo static::getClassName() . PHP_EOL;

}

}

class LynkCo01 extends Car

{

public static function getClassName()

{

return __CLASS__;

}

}

...

Car::who();

LynkCo01::who();

再次执行,打印结果如下:

Car

LynkCo01

表明后期静态绑定生效,即 static 指向的是调用它的方法所在的类,而不是定义时,所以称之为后期静态绑定。

此外,还可以通过 static::class 来指向当前调用类的类名,例如我们可以通过它来替代 __CLASS__,这样上述子类就没有必要重写 getClassName 方法了:

class Car

{

...

public static function getClassName()

{

return static::class;

}

public static function who()

{

echo static::getClassName() . PHP_EOL;

}

}

class LynkCo01 extends Car

{

}

代码执行结果和之前一样。

同理,self::class 则始终指向的是定义它的类,感兴趣的同学可以自行测试,这里不再演示了。self 和 static 各有其使用场景,后面我们会看到其实际的使用场景。

关于 PHP 静态属性和方法的使用就简单介绍到这里,明天,学院君将给大家介绍下 PHP 类中常见的魔术方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值