首先我要对 grrbrr404 说“谢谢”。他给了我一些想法,让我开始朝着正确的方向前进。
我最终确定的解决方案如下:
function inherit_this() {
$bt = debug_backtrace();
call_user_func(array($this, get_parent_class($bt[1]['class']) . '::do_something'));
}
它并不漂亮(我特别讨厌为此调用debug_backtrace()),但它会将对象上下文设置为$this,并处理从对象层次结构中间某处的方法调用该方法的情况。
对于那些发现我的示例令人困惑和/或想知道“您为什么要这样做?”的人。很抱歉,并提供以下附加示例,希望它更能说明问题并更接近原始问题。它要长得多,但希望能说明为什么我关心正确设置 $this,也说明为什么我不能硬编码任何特定的类名或使用 $this->method()。避免无限循环始终是我的首要任务。 :-)
class class1_required_type { }
class class2_required_type { }
class class3_required_type { }
class class4_required_type { }
class class1 {
protected $data = array();
protected function checkType($name, $value, $requiredType) {
print "In class1::checkType()\n";
if (get_class($value) === $requiredType) {
$backtrace = debug_backtrace();
call_user_func(array($this, get_parent_class($backtrace[1]['class']) . "::mySet"), $name, $value);
} else {
throw new Exception(get_class($this) . "::mySet('" . $name . "') requires an object of type '" . $requiredType . "', but got '" . get_class($value) . "'");
}
}
function mySet($name, $value) {
print "In class1::mySet()\n";
if ($name === 'class1_field') {
$this->checkType($name, $value, 'class1_required_type');
} else {
$this->data[$name] = $value;
}
}
function dump() {
foreach ($this->data as $key => $value) {
print "$key: " . get_class($value) . "\n";
}
}
}
class class2 extends class1 {
function mySet($name, $value) {
print "In class2::mySet()\n";
if ($name === 'class2_field') {
$this->checkType($name, $value, 'class2_required_type');
} else {
parent::mySet($name, $value);
}
}
}
class class3 extends class2 {
function mySet($name, $value) {
print "In class3::mySet()\n";
if ($name === 'class3_field') {
$this->checkType($name, $value, 'class3_required_type');
} else {
parent::mySet($name, $value);
}
}
}
class class4 extends class3 {
function mySet($name, $value) {
print "In class4::mySet()\n";
if ($name === 'class4_field') {
$this->checkType($name, $value, 'class4_required_type');
} else {
parent::mySet($name, $value);
}
}
}
$obj = new class4;
$obj->mySet('class3_field', new class3_required_type);
$obj->dump();
我试图避免重复“checkType()”函数,但即使在层次结构变得任意大时仍能提供正确的行为。
当然,更优雅的解决方案是最受欢迎的。