我需要一个继承的静态函数“call”来调用另一个被覆盖的静态函数“inner”。我可以用后期静态绑定来做到这一点,但我的主机还没有php5.3,所以我需要解决它。
class ClassA{
static function call()
{
return self::inner();
}
static function inner(){
return "Class A";
}
}
class ClassB extends ClassA{
static function inner(){
return "Class B";
}
}
echo "<p>Class A = " . ClassA::call();
echo "<p>Class B = " . ClassB::call();
我希望输出为:
A级= A级
B类= B类
但它是什么:
A级= A级
B类= A类
我的直觉告诉我,我应该能够在call()中写一些内容,以便在调用“call()”时检测引用的对象。因此,而不是self :: inner(),它会沿着calledclass :: inner()的方向行进。检测要从原始方法调用调用的inner()的正确版本。
答案 0 :(得分:3)
如果性能不是问题,可以使用debug_backtrace()来查找被调用的类:
$bt = debug_backtrace();
return get_class($bt[1]['object']);
答案 1 :(得分:2)
这是一个简单的例子。
<?php
class ClassA{
public function call(){
return $this->inner();
}
static function inner(){
return "Class A";
}
static function init($class){
return new $class();
}
}
class ClassB extends ClassA{
static function inner(){
return "Class B";
}
}
echo "<p>Class A = " . ClassA::init("ClassA")->call();
echo "<p>Class B = " . ClassB::init("ClassB")->call();
?>
如果您不想传递类名,可以向子类添加一个静态init函数,并将其显式传递给子类。这将允许您执行以下操作:ClassA :: init() - &gt; call()和ClassB :: init() - &gt; call()但会有一些次要代码重复。
答案 2 :(得分:1)
不幸的是,没有好的方法可以做到这一点(否则PHPers不会为这个功能欢呼这么多)。
你必须传递类名。 PHP&lt; 5.3对于具有动态类名的静态调用也没有很好的语法,这使整个事情变得更加丑陋:
static function call($class)
{
return call_user_func(array($class,"inner"));
}
…
ClassA::call("ClassA");
ClassB::call("ClassB");
如果您可以更改代码(而不是使用static
),那么单身人士会让它变得更加可忍受。您可以使用帮助功能来简化语法:
X("ClassA")->call();
X("ClassB")->call();
X函数应该查找,创建并返回类的实例。
答案 3 :(得分:1)
您可以使用对象实例而不是类。如果需要全局符号,可以使用全局变量。因为它们在PHP中相当笨重,所以一个技巧是将它包装在一个函数中。例如:
class ClassA {
function call() {
return $this->inner();
}
function inner() {
return "Class A";
}
}
function ClassA() {
static $instance;
return $instance ? $instance : new ClassA();
}
class ClassB extends ClassA {
function inner() {
return "Class B";
}
}
function ClassB() {
static $instance;
return $instance ? $instance : new ClassB();
}
echo "<p>Class A = " . ClassA()->call();
echo "<p>Class B = " . ClassB()->call();
但更好的想法可能是完全避免全球符号;它在Ruby / Rails中运行良好的原因是Ruby并没有像PHP那样拥有静态。一个类可以反弹并在运行时添加,这样可以轻松扩展框架。在PHP中,类总是最终的,因此在应用程序代码中引用它们是非常强烈的耦合程度。
答案 4 :(得分:1)
通常,当子进程调用父进程的方法时,需要进行后期静态绑定,而父进程又调用子进程的抽象静态方法。我是这样的一个帖子,并且不能使用static ::因为我的PHP不是5.3版本(或更高版本)。以下通过debug_backtrace()实现了后期静态绑定。
abstract class ParentClass
{
static function parent_method()
{
$child_class_str = self::get_child_class();
eval("\$r = ".$child_class_str."::abstract_static();");
return $r;
}// CHILD MUST OVERRIDE TO PUT ITSELF INTO TRACE
protected abstract static function abstract_static(); // THIS NEEDS LATE STATIC BINDING
private static function get_child_class()
{
$backtrace = debug_backtrace();
$num = count($backtrace);
for($i = 0; $i < $num; $i++)
{
if($backtrace[$i]["class"] !== __CLASS__)
return $backtrace[$i]["class"];
}
return null;
}
}
class ChildClass extends ParentClass
{
static function parent_method(){ return parent::parent_method(); }
protected static function abstract_static()
{
return __METHOD__."()";
}// From ParentClass
}
print "The call was: ". ChildClass::parent_method();
答案 5 :(得分:0)
由于您无法使用static ::,或get_called_class()或__callStatic, 你必须用一些指示来调用inner()函数 被叫类(如其他答案中所述)。一个实例 被叫的班级没问题。 您可以添加“伪静态”方法来模仿每个静态方法 你需要覆盖。这会使您的代码加倍,但是 通过这样做,我希望代码更容易升级一次 php5.3出现:只需删除所有 ps 方法和所有 函数引用它们(并在需要的地方将“self”更改为“static”。)
class ClassA{
static function call()
{
return self::inner();
}
static function inner(){
return "Class A";
}
public function _ps_call()
{
return $this->_ps_inner();
}
}
class ClassB extends ClassA{
public static function getInstance()
{
return new self();
}
public static function call()
{
return self::getInstance()->_ps_call();
}
static function inner()
{
return "Class B";
}
public function _ps_inner()
{
return self::inner();
}
}
echo "<p>Class A = " . ClassA::call();
echo "<p>Class B = " . ClassB::call();