php教程,如何在方法中代码判断归属于哪个class类?
发布于 作者:苏南大叔 来源:程序如此灵动~ 我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...
本文讨论在类方法里面确定当前类的方案途径,在自定义class
的时候,可以方便的确定当前代码的身份。主要的方法是常量__CLASS__
和函数get_class()
,同时和函数get_called_class()
做对比。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验文章。测试环境:win10
,nginx@1.15.11
,php@8.2.10-nts
。
当前类:__CLASS__ / get_class()
__CLASS__
的结果,恒等于get_class()
的结果,指的是当前的代码所在的实际的类。
也就是说:
- 如果当前代码实际在子类里面,则判断结果为子类。
- 如果在父类里面,即使方法被继承了,依然返回父类。
参考文档:
调用类:get_called_class()
get_called_class()
返回的是类方法的调用者是谁,主要用于类继承的情况。官方的说法是:获得后期静态绑定("Late Static Binding")类的名称。
get_called_class()
可能等于__CLASS__
或者get_class()
,则可能所有代码都在子类里面。get_called_class()
可能不等于__CLASS__
或者get_class()
,那么代码大概率是在父类里面。
参考文档:
父类:get_parent_class()
get_parent_class()
获得对象或者类的父类名字,它可以脱离类方法独立调用。没有父类的话,就显示为空(实际是个bool(false)
),并不显示自身。
测试代码一,最简单常见的情况
class S
{
public function test()
{
echo "from S", PHP_EOL;
echo "__CLASS__:",__CLASS__, PHP_EOL;
echo "get_class():",get_class(), PHP_EOL;
echo "get_called_class():",get_called_class(), PHP_EOL;
echo "get_parent_class():",get_parent_class(), PHP_EOL;
echo PHP_EOL;
}
}
$s = new S();
$s->test();
输出:
from S
__CLASS__:S
get_class():S
get_called_class():S
get_parent_class():
测试代码二,类继承
// ...
class N1 extends S
{
}
class N2 extends S
{
public function test()
{
echo "from N2", PHP_EOL;
echo "__CLASS__:",__CLASS__, PHP_EOL;
echo "get_class():",get_class(), PHP_EOL;
echo "get_called_class():",get_called_class(), PHP_EOL;
echo "get_parent_class():",get_parent_class(), PHP_EOL;
echo PHP_EOL;
}
}
$n1 = new N1();
$n1->test();
$n2 = new N2();
$n2->test();
输出:
from S
__CLASS__:S
get_class():S
get_called_class():N1
get_parent_class():
from N2
__CLASS__:N2
get_class():N2
get_called_class():N2
get_parent_class():S
在这个例子里面,
N1
继承了判断代码所在的方法,但是__CLASS__
和get_class()
诚实的反馈代码真实所在位置。N2
同样继承了对应方法,但是在其内部进行了改写,所以__CLASS__
和get_class()
的结果,暂时等于get_called_class()
的结果。但是,与get_parent_class()
的结果,并不相同。
测试代码三,使用trait
把公有的测试代码提取出来做一个trait
,看看结果会如何?
trait ssnn{
public function test()
{
echo "from ssnn", PHP_EOL;
echo "__CLASS__:",__CLASS__, PHP_EOL;
echo "get_class():",get_class(), PHP_EOL;
echo "get_called_class():",get_called_class(), PHP_EOL;
echo "get_parent_class():",get_parent_class(), PHP_EOL;
echo PHP_EOL;
}
}
class S
{
use ssnn;
}
class N1 extends S
{
}
class N2 extends S
{
use ssnn;
}
$s = new S();
$s->test();
$n1 = new N1();
$n1->test();
$n2 = new N2();
$n2->test();
结果输出:
from ssnn
__CLASS__:S
get_class():S
get_called_class():S
get_parent_class():
from ssnn
__CLASS__:S
get_class():S
get_called_class():N1
get_parent_class():
from ssnn
__CLASS__:N2
get_class():N2
get_called_class():N2
get_parent_class():S
从输出结果上来看,trait
代码很中立,吃谁的饭就替谁说话。和已知的测试结果一致,并不影响结果走向。
特例一
如果类存在于命名空间中,则测试代码的结果会带上命名空间的路径信息。
namespace SN;
//...
输出:
from ssnn
__CLASS__:SN\S
get_class():SN\S
get_called_class():SN\S
get_parent_class():
from ssnn
__CLASS__:SN\S
get_class():SN\S
get_called_class():SN\N1
get_parent_class():
from ssnn
__CLASS__:SN\N2
get_class():SN\N2
get_called_class():SN\N2
get_parent_class():SN\S
特例二
不在上下文中隐式获得被判断的类对象,而是直接调用:
$s = new S();
$n1 = new N1();
$n2 = new N2();
echo get_class($s),PHP_EOL; // S
echo get_class($n1),PHP_EOL; // N1
echo get_class($n2),PHP_EOL; // N2
// echo get_called_class($s);
// echo get_called_class($n1);
// echo get_called_class($n2);
echo get_parent_class($s),PHP_EOL; // 空
echo get_parent_class($n1),PHP_EOL; // S
echo get_parent_class($n2),PHP_EOL; // S
这里可以看到区别:
get_class()
,这个时候就变乖了,不在根据代码实际在哪个类里面做判断了。get_called_class()
,直接报错,不能这么用。get_parent_class()
,也变乖了,结果也不根据代码实际位置变化了。
思考题
根据本文的结论,看看下面的代码的运算结果是啥:
class S
{
public function test()
{
var_dump(__CLASS__);
var_dump(get_class());
var_dump(get_called_class());
var_dump(get_parent_class());
}
}
class N extends S
{
public function _test()
{
$this->test();
}
}
class NN extends N { }
$nn = new NN();
$nn->_test();
答案是:
newsn.net:这里是【评论】可见内容
相关链接
结束语
如果把相关测试代码放在方法里面,让它自己判断参数的话,可能由于代码位置的不同,产生和预期值不符的结果。同时,苏南大叔有个猜想,php
里面的这个继承,并不是说让子类拥有了对应的方法,而是让子类拥有了指挥父类对应的方法的能力。(细品...)
更多苏南大叔的php
经验文章,请点击:
如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。