bobo
bobo

Reputation: 8727

Changing return type when overidding a function in the subclass in PHP?

Is this bad? Or this is very common in PHP framework?

For example, in the parent class, there is a save() function which returns the number of rows affected in the database. Then in the child class, I override this function to do some pre-validation, and also would like to simply return a success/failed boolean value.

Upvotes: 4

Views: 6415

Answers (8)

funder7
funder7

Reputation: 1865

I've ended up here looking for a correct way of doing. In my case I'm speaking about a Test Class:

  • the original method returned a bool: success | failure
  • the test method returned an array instead, to return some debug info

That's how I've solved:

  • Added the "test" prefix in front of the method name;
  • In the php doc comment, I've added a @see tag, followed by the original method name;

I really like this solution, because by Ctrl clicking with phpStorm, I'm leaded to the original method.

In other cases probably I wouldn't change the return type, as explained by others, but the see tag can be used in a similar way.

Hope it helps! Keep on rocking ;)

Upvotes: 0

outis
outis

Reputation: 77450

You can return a more specified type, such as an instance of a descendant of the return type from the overridden method, without breaking a contract.

If the overridden method returned a boolean, the overriding method could instead return a number if 0 return value corresponded to the conditions that would cause the overridden method to return FALSE and non-zero values corresponded to a TRUE return value. This could still potentially cause problems if someone used the identical comparison operator (===) on the return value, but you typically only see this when (e.g.) a method might return both FALSE and 0 under different conditions.

In your example, the overriding return type is not more specific than the overridden return type, so you shouldn't do it.

Upvotes: 1

Matt Wonlaw
Matt Wonlaw

Reputation: 12473

The idea of inheritance is to allow clients to use the sub types of a class interchangeably. If you are changing return types of sub types then you are destroying the normative utility of inheritance and will just end up creating confusion: "Here I take a type of Collection, but is myCollection.add() going to return me a boolean or the element that was added or something else? I have no idea! I can't do anything anymore with this type! I'm going to have to make a method for each sub type in order to handle this problem!"

Upvotes: 3

Atli
Atli

Reputation: 7930

I agree, that this is generally a bad idea.

If you desperately need to pass another value out of the function, other than it's return value, you can add a pass-by-reference parameter. Or, in case of error messages, use Exceptions.

Upvotes: 2

Lukman
Lukman

Reputation: 19164

I agree with consensus that it's bad to change the type (or even the meaning) of the return value.

Here is an illustration how it will be bad:

Let say you have a function that accepts a string and a 'Writer':

function printThroughWriter(String $text, Writer $writer) {
    $count = $writer->write($text);
    print "Writer '".get_class($writer)."' printed $count characters.";
}

And here is the original 'Writer' class:

class Writer {
    public function write(String $text) {
        print $text;
        return strlen($text);
    }
}

What if we pass a 'LazyWriter' instead to the function:

class LazyWriter extends Writer {
    public function write(String $text) {
        return true;
    }
}

The assumption that the return value of the Writer::write() is the number of characters in printThroughWriter has been broken, thus causing inconsistency.

Upvotes: 5

Noah Goodrich
Noah Goodrich

Reputation: 25263

While there is nothing enforcing return types in PHP, it is a good idea to remain consistent with overridden methods because to do otherwise means that you will increase coupling and decrease encapsulation.

Think of public methods and their return types in terms of outlets and appliances. Any appliance should be able to plug into any outlet and every outlet should output the same amount of energy to each appliance, unless of course the outlet has been specifically designed for a specific type of appliance. What would happen if someone decided that green outlets should output one amount of energy and red ones another. Suddenly you'd have to always be concerned with the specific class of outlet that your appliance is dealing with.

Designing public methods and properties is exactly the same and overridden methods and properties should always behave consistently regardless of the context in which they are accessed.

Upvotes: 2

strager
strager

Reputation: 90062

You should be overriding the underlying code, not the contract.

So, no, it's not good to change the return values (which is part of the contract).

Upvotes: 3

NawaMan
NawaMan

Reputation: 25687

Yes it is bad. It will be hard for the client of that method to be know that to expect. UNLESS, the method is designed to handle it (which in this case, it does not seems like).

I will strongly advice against it.

Upvotes: 2

Related Questions