下面是一个示例类层次结构和代码。我正在寻找的是一种方法来确定"ChildClass1"或"ChildClass2"是否具有对其调用的静态方法 whoAmI() 而无需在每个子类中重新实现它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| ?php
abstract class ParentClass {
public static function whoAmI () {
// NOT correct, always gives 'ParentClass'
$class = __CLASS__;
// NOT correct, always gives 'ParentClass'.
// Also very round-about and likely slow.
$trace = debug_backtrace();
$class = $trace[0]['class'];
return $class;
}
}
class ChildClass1 extends ParentClass {
}
class ChildClass2 extends ParentClass {
}
// Shows 'ParentClass'
// Want to show 'ChildClass1'
print ChildClass1::whoAmI();
print"\
";
// Shows 'ParentClass'
// Want to show 'ChildClass2'
print ChildClass2::whoAmI();
print"\
"; |
我相信您所指的是一个已知的 php 错误。 Php 5.3 旨在通过新的后期静态绑定功能解决此问题。
http://www.colder.ch/news/08-24-2007/28/late-static-bindings-expl.html
既然 PHP 5.3 在野外广泛使用,我想汇总这个问题的答案,以反映最新可用的技术。
正如其他答案中提到的,PHP 5.3 通过新的 static 关键字引入了后期静态绑定。此外,还提供了一个新的 get_called_class() 函数,该函数只能在类方法(实例或静态)中使用。
为了确定这个问题中所问的类,get_called_class() 函数是合适的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| ?php
abstract class ParentClass {
public static function whoAmI () {
return get_called_class();
}
}
class ChildClass1 extends ParentClass {
}
class ChildClass2 extends ParentClass {
}
// Shows 'ChildClass1'
print ChildClass1::whoAmI();
print"\
";
// Shows 'ChildClass2'
print ChildClass2::whoAmI();
print"\
"; |
用户为 get_called_class() 提供的注释包括一些示例实现,这些示例实现也应该在 PHP 5.2 中使用 debug_backtrace()。
类识别通常是多态性没有被很好理解的症状。
ChildClass1 和 ChildClass2 的客户端不需要区分它们。
没有任何地方可以让任何班级询问someObject.whoAmI()。
当你有编写 if someObject.whoAmI() == 'ChildClass1' { do X(someObject) } 的冲动时,你应该真正为 ParentClass 添加一个 X() 方法,并在各种 ChildClasses 中实现各种实现。
这种"运行时类型识别"几乎总是可以用适当的多态类设计代替。
从 PHP 5.3 开始,可以使用 static 关键字,但现在还不行。
没有。等待 PHP 5.3。