PHP严格标准:声明应兼容
我有以下层次结构的类:
class O_Base {...} class O extends O_Base {...} abstract class A_Abstract { public function save(O_Base $obj) {...} } class A extends A_Abstract { public function save(O $obj) { echo 'save!'; } } $o = new O; $a = new A; $a->save($o); 当我运行这个代码,我得到消息:
我知道E_STRICT错误级别,但我找不到(并理解)该行为的原因.有谁能够帮助我?
您的代码明确违反了
the Liskov Substitution principle.抽象类需要将O_Base的一个实例传递给save方法,因此A_Abstract的所有子节点都应该被定义为可以接受O_Base的所有实例.您的子类实现了进一步限制API的保存版本.
see another example here
在你的代码中,A违反了Abstract_A强制执行/描述的合同.就像在现实生活中一样,如果您签署合同,您必须在某些条款上达成一致,并且都将与您将要使用的术语达成一致.这就是为什么大多数合同是以各方命名的方式开始的,然后再说“X以后就被称为员工”. 考虑这个: abstract class Foo { abstract public function save(Guaranteed $obj); //or worse still: final public function doStuff(Guaranteed $obj) { $obj->setSomething('to string'); return $this->save($obj);//<====!!!! } } class FBar extends Foo { public function save(Guaranteed $obj) { return $obj->setFine(true); } } class FBar2 extends Foo { public function save(ChildOfGuaranteed $obj) {//FAIL: This method is required by Foo::doStuff to accept ALL instances of Guaranteed } } 看这里,在这种情况下,完全有效的抽象类正在调用一个保证实例的save方法.如果您被允许在此类的子级中强制执行更严格的类型提示,则可以轻松地打破此doStuff方法.为了帮助您保护自己免受这些自我伤害的伤害,儿童课程不应该被允许对父母继承的方法执行更严格的类型. $arg = new OtherChildOfGuaranteed; $array = array( 'fb' => new FBar,'fb2' => new FBar2 ); foreach($array as $k => $class) { if ($class instanceof Foo) $class->save($arg); } 现在,如果您只是在方法签名中提示“保证”,则此操作将正常工作.但是在第二种情况下,我们已经提出了类型提示有点太严格,这个代码将导致致命的错误.在一个更复杂的项目中调试这个有趣的乐趣… PHP在很多情况下是非常原谅的,如果不是宽恕,但不在这里.而不是让你搔头,直到你的听力下降,PHP非常明智地给你一个头脑,说你的方法的执行违反了合同,所以你必须解决这个问题. 现在,快速的解决方法(也是一个常用的)将是这样的: class FBar2 extends Foo { /** * FBar2 save implementation requires instance of ChildOfGuaranteed * Signature enforced by Foo * @return Fbar2 * @throw InvalidArgumentException **/ public function save(Guaranteed $obj) { if (!$obj instanceof ChildOfGuaranteed) throw new InvalidArgumentException(__METHOD__.' Expects instance of ChildOfGuaranteed,you passed '.get_class($obj)); //do save here... } } 所以,你只是按照原样离开抽象类型提示,但是使用docblock来记录你的代码 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |