PHP后期静态绑定分析与应用
1. 范围解析操作符 (::)
- 可以用于访问静态成员,类常量,还可以用于覆盖类中的属性和方法。
- self,parent 和 static 这三个特殊的关键字是用于在类定义的内部对其属性或方法进行访问的。
- parent用于调用父类中被覆盖的属性或方法(出现在哪里,就将解析为相应类的父类)。
- self用于调用本类中的方法或属性(出现在哪里,就将解析为相应的类;注意与this区别,this指向当前实例化的对象)。
- 当一个子类覆盖其父类中的方法时,PHP不会调用父类中已被覆盖的方法。是否调用父类的方法取决于子类。
2.将类的继承实现。
示例
class Demo{ //定义一个Demo类
const A = '曹操';
const B = '刘备';
public static $A = '孙权';
public static $B = '周瑜';
static function testSelf(){
echo self::A.self::B.self::$A.self::$B;
}
//在Demo中用常量和静态属性都赋值。通过self输出。
//self用于类本身static的调用
}
class Demo1 extends Demo{ //继承Demo类
const A = "关羽";
const B = '赵云';
public static $A = '张飞';
public static $B = '张辽';
static function testParent()
{
echo parent::A.parent::B.parent::$A.parent::$B;
echo '<br>';
echo self::A.self::B.self::$A.self::$B;
}
//在Demo中用常量和静态属性都赋值。通过self与parent输出。
//parent用于类的父级调用
}
class Demo2 extends Demo1{
const A = "吕布";
const B = '貂蝉';
static function testClass()
{
echo 'Demo:'.Demo::A.'Demo1:'.parent::A.'Demo2:'.self::A;
}
}
//在Demo2中用常量赋值。通过类名::调用Demo的常量A
//parent调用父级Demo1中的常量A。
//self调用类本身的常量A
Demo::testSelf();
echo "<HR>";
Demo1::testParent();
echo "<HR>";
Demo2::testClass();
示例图
总结:self调用类本身,parent调用父级,类名::调用任意类中的静态
3.Static(静态)关键字
- 在函数体内的修饰变量的static关键字用于定义静态局部变量。
- 用于修饰类成员函数和成员变量时用于声明静态成员。
- (PHP5.3之后)在作用域解析符(::)前又表示静态延迟绑定的特殊类。
定义静态方法,静态属性
(a)声明类属性或方法为静态,就可以不实例化类而直接访问。
(b)静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)
(c)如果没有指定访问控制,属性和方法默认为公有。
(d)由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。
(e)静态属性不可以由对象通过 -> 操作符来访问。
(f)用静态方式调用一个非静态方法会导致一个 E_STRICT 级别的错误。
(g)就像其它所有的 PHP 静态变量一样,静态属性只能被初始化为文字或常量,不能使用表达式。所以可以把静态属性初始化为整数或数组,但不能初始化为另一个变量或函数返回值,也不能指向一个对象。
示例
class Demo
{
public static $name = '刘备';
static function demoValue()
{
return 'Demo调用类本身:'.self::$name;
}
}
class Demo1 extends Demo
{
static $name ='曹操';
static function demo1Value()
{
return 'Demo1:调用父级:'.parent::$name.' | 调用类本身:'.self::$name;
}
}
class Demo2 extends Demo1
{
public static $name = '孙权';
static function demo2Value()
{
return 'Demo2:调用类本身:'.self::$name;
}
}
echo Demo::demoValue();
echo '<hr>';
echo Demo1::demo1Value();
echo '<hr>';
echo Demo2::demo2Value();
echo '<hr>';
总结:在例子中使用static静态申明,默认publice可以不写。
4.后期静态绑定(late static binding)
(a)用于在继承范围内引用静态调用的类。
(b)转发调用与非转发调用
- b-1 转发调用:
指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。 - b-2 非转发调用:
明确指定类名的静态调用(例如Demo::demo())
非静态调用(例如$Demo->demo())
(c)后期静态绑定工作原理
示例
<?php
class Demo {
public static function testDemo() { //定义一个testDemo静态方法
echo '我是Demo->testDemo中的获取当前类名:'.__CLASS__."<hr>"; //获取当前的类名
static::showTest(); //使用static调用showTest
}
public static function showTest() {
echo '我是Demo->testDemo1中的获取当前类名:'.__CLASS__."<hr>";
}
}
class Demo1 extends Demo {
public static function testDemo2() {
echo "Demo::testDemo():".Demo::testDemo()."<hr>";
echo "parent::testDemo():".parent::testDemo()."<hr>";
echo "self::testDemo():".self::testDemo()."<hr>";
}
public static function showTest() {
echo '我是Demo1->showTest中的获取当前类名:'.__CLASS__."<hr>";
}
}
class Demo2 extends Demo1 {
public static function showTest() {
echo '我是Demo2->showTest中的获取当前类名:'.__CLASS__."<hr>";
}
}
Demo2::testDemo2();
总结:用静态testDemo2,通过类名::,父级调用(parent),类本身调用(self),调用,加深对静态调用的认识,案例中使用了static::对类本身的静态方法调用,
5.使用forward_static_call()
- 调用一个静态方法、用于后期静态绑定,不能用于类外部
示例:
<?php
class A
{
static $name = '曹操';
public static function test() {
echo static::$name."<hr>";
//static调用静态$name是类本身调用
}
}
class B extends A
{
static $name ='刘备';
public static function test() {
echo parent::$name, "<hr>";
//这个如果不调用父级的$name默认是类本身
forward_static_call(array('A', 'test'));
//调用A类中的test静态方法
forward_static_call( 'test');
//调用类外部的test
forward_static_call(array('C','test'));
//调用C类中的test静态方法
}
}
class C extends B
{
static $name ='公孙策';
public static function test()
{
echo self::$name."<hr>";
//使用self调用的是类本身同等static
}
}
B::test();
function test() {
echo "孙权"."<hr>";
}
?>
示例图:
总结:forward_static_call 只能对本身和下类和外部函数进行操作,不能操作上类。
6.使用get_called_class()
- 获取静态绑定后的类名;
示例:
<?php
class A
{
public static function className()
{
echo __CLASS__.'<hr>';
echo __METHOD__.'<hr>';
echo __FUNCTION__.'<hr>';
return get_called_class();
// get_called_class 同等于__CLASS__
}
}
echo A::className();
总结:
- 在PHP后期静态绑定和分析学习中对.
- static 调用类本身同等于self
- parent 调用父类
- self 调用类本身
- forward_static_call 对类本身和下类操作,只能通过parent对上类进行操作
- get_called_class 获取静态绑定后的类名