如何在没有严格警告的情况下正确地扩展使用其他扩展类的PHP类


How do you properly extend PHP classes that use other extended classes without strict warnings

假设我有两个类(我在这里简化了逻辑):

class Table {
    public function addRow (Row $row){
        $this->row = $row;
    }
    // lots of code
}
class Row {
    // lots of code
}

我想扩展表类来做类似的事情,所以我创建了两个新类:

class SpecialTable extends Table{
    public function addRow (SpecialRow $row){
        parent::addRow($row);
    }
    // lots of code
}
class SpecialRow extends Row{
    // lots of code
}

当我尝试将SpecialRow添加到SpecialTable对象时,我会收到类似以下的警告:

PHP Strict standards:  Declaration of SpecialTable::addRow() should be compatible with that of Table::addRow() in /SpecialTable.php on line XX

有人能帮我吗?这是一种糟糕的做法吗?我应该用不同的方式编码它?还是这只是一个我应该忽略的警告?

非常感谢您的建议/指导。

如果您要更改参数类型,您可能应该使用类似SpecialTable::addSpecialRow()的名称,否则SpecialTable实际上并没有扩展表,而是重载它(PHP不支持)。

根据您的简化示例,它应该是public function addRow(Row $row),因为您只是调用父级。根据您在该函数中对$row实际执行的操作,您可以键入hint Row并在代码中检查它是否是SpecialRow,或者如果不需要它的Special,则只使用row。

确保SpecialRow从Row:扩展

class SpecialRow extends Row {
    // lots of code
}

SpecialTable扩展自Table:

class SpecialTable extends Table {
    // lots of code
}

如果RowSpecialRow没有直接关系(其中SpecialRow是专门的Row,因此应该是extend Row),则可以使用接口。PHP不支持没有一些疯狂丑陋的方法重载,所以一个替代方案可能是这样的:

接口

interface IRow
{
        // interface body
}

行类

class Row implements IRow
{
}
class SpecialRow implements IRow
{
}

表类

class Table
{
        public function addRow(IRow $row)
        {
                $this->row = $row;
        }
}
class SpecialTable
{
        public function addRow(IRow $row)
        {
                $this->row = $row;
        }
}

实施

$t = new Table();
$st = new SpecialTable();
$r = new Row();
$sr = new SpecialRow();
$t->addRow($r);
$st->addRow($sr);

http://ideone.com/TsVw5

由于它不遵循PHP的标准,我称之为糟糕的做法。关键是派生类应该总是像它的祖先一样工作。因此,期望Row参数的类可以以相同的方式处理SpecialRow。你是在扩展类,而不是重载它。我建议为此添加另一个方法。