在我的很多PHP课程中,我都有这段代码:
private $strError = "";
private $intErrorCode = NULL;
private $blnError = FALSE;
public function isError() {
return $this->blnError;
}
public function getErrorCode() {
return $this->intErrorCode;
}
private function setError( $strError, $intErrorCode = NULL ) {
$this->blnError = TRUE;
$this->intErrorCode = $intErrorCode;
$this->strError = $strError;
}
关键在于外部代码可以知道某个对象是否有错误状态,错误的字符串是什么等等。但是要在一堆不同的类中使用这个确切的代码是重复的!
我喜欢在我可以做的地方进行双扩展
class childClass extends parentClass, error {
...
}
并且具有天生的属性和方法,但PHP不支持多重继承。我正在考虑做的是创建一个存在于每个类中的错误类。如果我公开,我可以直接通过对象
来调用它if ( $myObject->error->isError() ) {...}
但也不会使其错误状态可以从包含类
之外设置$myObject->error->setError("I shouldn't be doing this here");
我宁愿避免?
或者我可以在包含类中编写'gateway'函数,它对错误对象进行适当的调用,并防止从外部设置错误状态,
class childClass extends parentClass {
private $error;
public function __construct(...) {
...
$error = & new error();
...
}
public function isError() {...}
public function getError() {...}
public function getErrorCode() {...}
private function setError() {...}
...
}
但是这导致(某些)我试图避免的代码重复。
这里的最佳解决方案是什么?我正在尝试为许多对象提供错误状态的功能,以便外部世界可以看到他们的错误状态,重复次数最少。
答案 0 :(得分:3)
使用合成而不是继承。
class Errors {
private $strError = "";
private $intErrorCode = NULL;
private $blnError = FALSE;
public function isError() {
return $this->blnError;
}
public function getErrorCode() {
return $this->intErrorCode;
}
private function setError( $strError, $intErrorCode = NULL ) {
$this->blnError = TRUE;
$this->intErrorCode = $intErrorCode;
$this->strError = $strError;
}
}
现在使用私有实例变量来引用它:
class childClass extends parentClass {
private $errors = new Errors();
...
}
private
可见性会阻止您在课堂外引用$errors
。
也无需在isError()
内创建getError()
,childClass
等(因此无需担心代码重复)。只需致电$this->errors->isError()
,$this->errors->getError()
等。如果您仍然想要实施这些方法,请按照以下建议,指定一个界面。
答案 1 :(得分:1)
你也可以滥用__call
魔法来做同样的事情:
public function __call($name, array $arguments) {
$name = strtolower($name);
if (isset($this->methods[$name])) {
array_unshift($arguments, $this);
return call_user_func_array($this->methods[$name], $arguments);
}
throw new BadMethodCallException('Method does not exist');
}
请注意,我说滥用......理想情况下,我会想到一个不同的架构,而不是到处都有这些“常用方法”。为什么不使用例外而不是检查$foo->isError
?如果这不合适,为什么不装饰一个类?
class Errors
protected $object = null;
public function __construct($object) {
$this->object = $object;
}
public function __call($method, array $arguments) {
$callback = array($this->object, $method);
if (is_callable($callback)) {
return call_user_func_array($callback, $arguments);
}
throw new BadMethodCallException('Method does not exist');
}
public function __get($name) { return $this->object->$name; }
public function __set($name, $value) { $this->object->$name = $value; }
// Your methods here
public function isInstance($name) { return $this->object instanceof $name; }
}
然后只需“包裹”该类中的现有对象:
$obj = new Errors($obj);
$obj->foo();
答案 2 :(得分:1)
从PHP 5.4开始,您可以使用Traits。
例如,您可以将Trait称为ErrorTrait,如下所示:
trait ErrorTrait {
private $strError = "";
private $intErrorCode = NULL;
private $blnError = FALSE;
public function isError() {
return $this->blnError;
}
public function getErrorCode() {
return $this->intErrorCode;
}
private function setError( $strError, $intErrorCode = NULL ) {
$this->blnError = TRUE;
$this->intErrorCode = $intErrorCode;
$this->strError = $strError;
}
}
然后你会像这样定义你的子类:
class childClass extends parentClass {
use ErrorTrait;
...
}
Traits的工作基本上就像复制/粘贴一样,因此特征中的所有代码都可以在类中使用(没有代码重复)。