我想扩展类有最终构造函数(在我的例子中是SimpleXMLElement),但是我有问题,因为当我使用时:
class myclass extends SimpleXMLElement {
function __construct($xmlVersion='1.0', $xmlEncoding='ISO-8859-1', $rootName='root'){
parent::__construct("<?xml version='$xmlVersion' encoding='$xmlEncoding'?><$rootName />");
}
我收到错误:
致命错误:无法覆盖最终版 方法SimpleXMLElement :: __ construct()
当我删除构造函数时,我收到此错误:
致命错误:未捕获的异常 信息'异常' “的SimpleXMLElement :: __构建体() 期望至少有一个参数,0给出'
我错过了一些或者不理解如何正确调用最终的父构造函数。 我不希望覆盖方法只是扩展类,但我无法扩展,因为它需要__construct()。所以我错过了一些东西,然后又开始了。
有人可以解释我错在哪里吗?
答案 0 :(得分:3)
在这种情况下,我会使用Delegate包装器设计。你应该在这里考虑构成而不是继承。
答案 1 :(得分:3)
我刚刚完成了这件事。您不需要扩展它。创建一个包含SimpleXMLElement对象的类。我相信这就是尼古拉的意思。
class XmlResultSet
{
public $xmlObjs = array();
public function __construct(array $xmlFiles)
{
foreach ($xmlFiles as $file) {
$this->xmlObjs[] = new XmlResult($file);
}
}
}
class XmlResult
{
private $xmlObj;
public function __construct($file)
{
try {
$this->xmlObj = new SimpleXMLElement($file, 0, true);
}
catch (Exception $e) {
throw new MyException("Invalid argument ($this)($file)(" . $e .
")", PHP_ERRORS);
}
}
public function otherFunctions()
{
return $this->xmlObj->movie['name']; // whatever
}
}
答案 2 :(得分:2)
class myclass extends SimpleXMLElement {
public static function getInstance($xmlversion = '1.0', $xmlencoding = 'ISO-8859-1', $rootName='root') {
return new self("<?xml version='$xmlVersion' encoding='$xmlEncoding'?><$rootName />");
}
}
答案 3 :(得分:1)
嗯,final
意味着最终。没有覆盖该方法。即使你问得很好。我建议为你的新类添加一个静态make()方法。类似的东西:
class myclass extends SimpleXMLElement {
static function make($data, $xmlVersion='1.0', $xmlEncoding='ISO-8859-1', $rootName='root'){
$obj=parent::__construct($data);
$obj->x=$xmlVersion;
$obj->e=$xmlEncoding;
$obj->r=$rootName;
return $obj;
}
}
答案 4 :(得分:0)
There can be valid reasons to extend a third-party "final" class, resulting in more readable/maintainable code than completely duplicating it or creating some convoluted work-around. And certainly preferable over changing the third-party source code and removing the "final" keyword.
PHP supplies the extension "Componere" to accomplish such a feat in those rare cases where it truly is the best option. Below an example that shows how a the child class can be defined as a "trait", which can then be used to dynamically extend a final parent class:
<?php
declare(strict_types=1);
/*
* Final class would normally prevent extending.
*/
final class ParentC
{
public $parentvar;
public $secondvar;
function __construct() { echo( "\r\n<br/>".$this->parentvar = 'set by '.get_class().'->parentconstruct' ); }
function parentf() { echo( "\r\n<br/>".get_class().'->parentf >> '.$this->parentvar ); }
}
/*
* Extended class members.
*/
trait ChildC /* extends ParentC */
{
function __construct() {
// Call parent constructor.
parent::__construct();
// Access an inherited property set by parent constructor.
echo( "\r\n<br/>".get_class().'->overridden_constructor >> '.$this->parentvar );
}
function parentf() {
// Call overridden parent method.
parent::parentf();
// Access an inherited property set by constructor.
echo( "\r\n<br/>".get_class().'->overridden_parentf >> '.$this->parentvar );
}
function dynamicf( $parm = null ) {
// Populate a parent class property.
$this->secondvar = empty( $parm ) ? 'set by '.get_class().'->dynamicf' : $parm;
// Access an inherited property set by parent constructor.
echo( "\r\n<br/>".get_class().'->dynamicf >> '.$this->parentvar );
}
}
/*
* Register the dynamic child class "ChildC", which is
* derived by extending "ParentC" with members supplied as "ChildC" trait.
*/
$definition = new \Componere\Definition( 'ChildC', ParentC::class );
$definition->addTrait( 'ChildC' );
$definition->register();
/*
* Instantiate the dynamic child class,
* and access its own and inherited members.
*/
$dyno = new ChildC;
$dyno->parentf();
$dyno->dynamicf( 'myvalue ');
// Our object is also recognized as instance of parent!
var_dump( $dyno instanceof ChildC, $dyno instanceof ParentC, is_a( $dyno, 'ParentC') );
var_dump( $dyno );
?>
答案 5 :(得分:-3)
我知道这是一个老帖子,但我刚才遇到了类似的问题。我实际上是两次包含相同的类文件。使用include_once()或require_once()而不是include()或require()。