2008-09-17 64 views
1

下面是一个示例类层次结构和代码。我正在寻找的是一种确定'ChildClass1'或'ChildClass2'是否具有静态方法whoAmI()而不是在每个子类中重新实现的方法。有没有什么办法在静态方法中检测目标类?

<?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 "\n"; 

// Shows 'ParentClass' 
// Want to show 'ChildClass2' 
print ChildClass2::whoAmI(); 
print "\n"; 

回答

2

既然PHP 5.3在野外广泛存在,我想把这个问题的总结答案放在一起,以反映新的可用技术。

正如其他答案中提到的那样,PHP 5.3通过一个新的static关键字引入了Late Static Binding。另外,还可以使用新的get_called_class()函数,该函数只能在类方法(实例或静态)中使用。

为了确定班级为被问到这个问题的目的,get_called_class()功能适用:

<?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 "\n"; 

// Shows 'ChildClass2' 
print ChildClass2::whoAmI(); 
print "\n"; 

user contributed notes for get_called_class()包括了一些简单的实现,应该在PHP 5.2通过利用工作,以及debug_backtrace()

2

类别识别通常是一个不太明白的多态现象的症状。

ChildClass1和ChildClass2的客户端不需要区分它们。

任何班级都不应该询问someObject.whoAmI()

无论何时你有写if someObject.whoAmI() == 'ChildClass1' { do X(someObject) }的冲动,你真的应该在ParentClass中添加一个X()方法,并在各个ChildClass中使用各种实现。

这种“运行时类型识别”几乎总是可以用适当的多态类设计来代替。

+0

@ S.Lott我完全同意,如果在真实代码中使用这种方法将是一个漏洞抽象。在这种情况下,该方法就是提供可理解的样本。我想确定子类的原因是,我可以使用静态实例创建方法,这些方法由类层次结构的所有成员共享,但仍然调用相应的子构造函数。 – 2009-09-06 03:54:30

1

从PHP 5.3开始,可以使用static keyword,但现在不可能。

相关问题