YakobeYak
YakobeYak

Reputation: 555

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

Imagine i have 2 classes (i've simplified the logic here):

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

And i want to extend the table class to do something similar so i create 2 new classes:

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

When i try to add a SpecialRow to a SpecialTable object i get a warning similar to:

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

Can someone help me here? Is this bad practice and i should code it differently? Or is it just a warning that i should ignore?

Many thanks for any suggestions / guidance.

Upvotes: 1

Views: 1038

Answers (4)

Demian Brecht
Demian Brecht

Reputation: 21378

If Row and SpecialRow aren't directly related (where SpecialRow is a specialized Row and therefore should extend Row), you could use an interface. PHP doesn't support method overloading without some crazy ugliness, so an alternative might be something like this:

Interface:

interface IRow
{
        // interface body
}

Row classes:

class Row implements IRow
{
}

class SpecialRow implements IRow
{
}

Table classes:

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

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

Implementation:

$t = new Table();
$st = new SpecialTable();

$r = new Row();
$sr = new SpecialRow();

$t->addRow($r);
$st->addRow($sr);

http://ideone.com/TsVw5

Upvotes: 1

runfalk
runfalk

Reputation: 1996

Since it doesn't follow PHP's standards I'd call it bad practice. The point is that a derivative class should always work like its ancestor. So classes expecting a Row argument can handle a SpecialRow the same way. You're extending the class, not overloading it. I'd suggest adding another method for this purpose.

Upvotes: 0

Peter Stone
Peter Stone

Reputation: 3776

You should probably use a name like SpecialTable::addSpecialRow() if you're changing the argument type - otherwise SpecialTable doesn't actually extend Table, it overloads it (which isn't supported in PHP).

Based on your simplified example, it should be public function addRow(Row $row) since you just call the parent. Depending on what you're actually doing to $row in that function, you could type-hint Row and check whether it's a SpecialRow in code, or just use Row if you don't need its Specialness.

Upvotes: 2

Yeroon
Yeroon

Reputation: 3243

Make sure SpecialRow extends from Row:

class SpecialRow extends Row {
    // lots of code
}

And that SpecialTable extends from Table:

class SpecialTable extends Table {
    // lots of code
}

Upvotes: 1

Related Questions