之前有一篇笔记里面提到过get_class
这个方法,这篇笔记主要是get_class
和get_called_class
的区别,以及静态绑定
相关的知识
假如说代码如下,有两个类,其中类B是类A的子类
class A {
public function test(){
var_dump(get_class());
var_dump(get_called_class());
}
public static function test2(){
var_dump(get_class());
var_dump(get_called_class());
}
}
class B extends A {
public function test3(){
var_dump(get_class());
var_dump(get_called_class());
}
public static function test4(){
var_dump(get_class());
var_dump(get_called_class());
}
}
那么看下面这个打印出啥
$varA = new A();
$varA->test();
A::test2();
打印结果是
string(1) "A"
string(1) "A"
string(1) "A"
string(1) "A"
看下面这个打印出啥
$varB = new B();
$varB->test();
$varB->test3();
B::test2();
B::test4();
打印结果是
string(1) "A"
string(1) "B"
string(1) "B"
string(1) "B"
string(1) "A"
string(1) "B"
string(1) "B"
string(1) "B"
get_class($obj)
的作用是:返回实例所属类的名字,如果在类里面可以省略参数。
get_called_class()
的作用是:获取后期静态绑定("Late Static Binding")类的名称。该方法如果不是在类里面调用,会返回FALSE
。
我理解get_called_class()
的作用就是获取最初调用这个方法的类名。比如说子类B调用父类A的方法,那么get_called_class()的结果就是B。但是手册上关于这个解释我觉得很奇怪,反而引入了一个新的概念——Late Static Binding
手册上对于Late Static Binding
的解释是这样的:
“后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。
什么鬼!就不能说人话吗!还是看看英文版吧。╭(╯^╰)╮
我在之前的笔记里面提到过,类的静态属性和静态方法,需要添加关键字static
。
而后期静态绑定(又叫:延迟绑定)也涉及到了static
。
static::
中的static其实是运行时所在类的别名,并不是定义类时所在的那个类名。这个东西可以实现在父类中能够调用子类的方法和属性。
注意:static::
与静态属性、静态方法不是同一个概念。
上面说了一大通,那么这个Late Static Binding
到底有什么用呢?
说得简单点儿——父类可以调用子类的方法、属性。
以前在学校里学过一点点C++
的时候,只知道子类可以调用父类的方法和属性,不知道还可以反过来的。那么下面就来看看实例。
举例:父类Model_Base
,子类Model_User
。
class Model_Base {
public function getAll() {
echo static::$table;
}
}
class Model_User extends Model_Base {
protected static $table = 'user';
}
$var = new Model_User();
$var->getAll();
打印结果是:
user
在父类Model_Base
里面通过static::
获取到了子类的静态属性。
如果大家觉得不够直观,那么示例可以改成如下这样,比较好理解。下面示例的意思就是,从user
表和account
表里面查出所有记录。
class Model_Base {
public function getAll() {
$tableName = static::$table;
// 执行sql语句
$sql = 'select * from ' . $tableName . ';';
……
// 返回数据库查询结果
……
}
}
class Model_User extends Model_Base {
protected static $table = 'user';
}
class Model_Account extends Model_Base {
protected static $table = 'account';
}
$user = new Model_User();
$user->getAll();
$account = new Model_Account();
$account->getAll();
在上方的代码里面用到了static::
,其实也可以用get_called_class
来实现,比如
class Model_Base {
public function getAll() {
$clname = get_called_class();
$tableName = $clname::$table;
// 执行sql语句
$sql = 'select * from ' . $tableName . ';';
……
// 返回数据库查询结果
……
}
}
本文上面提到过,static::
中static存放的是运行时所在类的别名,那么与get_called_class()
的返回结果是一样的。
上面的举的例子是调用了子类的静态属性,那么调用子类的静态方法也是一样的。例子如下:
class Model_Base {
public function getAll() {
$clname = get_called_class();
$clname::info();
echo "\n";
static::info();
}
}
class Model_User extends Model_Base {
protected static $table = 'user';
protected static function info() {
echo 'table name is ' . self::$table;
}
}
$var = new Model_User();
$var->getAll();
整个打印结果是:
table name is user
table name is user
再次说明了get_called_class()
与static::
里面的static所代表的类名是一样的。
上面都是调用静态属性、静态方法,如果是调用非静态属性、非静态方法呢?——看下面的例子
class Model_Base {
public function getAll() {
$u1 = new static();
$u1->nameInfo();
echo "\n";
echo $u1->table;
echo "\n";
$clname = get_called_class();
$u2 = new $clname();
$u2->nameInfo();
echo "\n";
echo $u2->table;
}
}
class Model_User extends Model_Base {
protected $table = 'user';
protected function nameInfo() {
echo 'subclass table name is user';
}
}
$var = new Model_User();
$var->getAll();
打印结果是:
subclass table name is user
user
subclass table name is user
user
上面的这个例子,可以看到非静态属性和非静态方法都能被调用。