Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can parameter types be specialized in PHP

Say we've got the following two classes:

abstract class Foo {
    public abstract function run(TypeA $object);
}

class Bar extends Foo {
    public function run(TypeB $object) {
        // Some code here
    }
}

The class TypeB extends the class TypeA.

Trying to use this yields the following error message:

Declaration of Bar::run() must be compatible with that of Foo::run()

Is PHP really this broken when it comes to parameter types, or am I just missing the point here?

like image 293
Johan Fredrik Varen Avatar asked Jan 21 '23 20:01

Johan Fredrik Varen


2 Answers


This answer is outdated since PHP 7.4 (partially since 7.2).


The behavior you describe is called covariance and is simply not supported in PHP. I don't know the internals but I might suspect that PHP's core does not evaluate the inheritance tree at all when applying the so called "type hint" checks.

By the way, PHP also doesn't support contravariance on those type-hints (a feature commonly support in other OOP languages) - most likely to the reason is suspected above. So this doesn't work either:

abstract class Foo {
    public abstract function run(TypeB $object);
}

class Bar extends Foo {
    public function run(TypeA $object) {
        // Some code here
    }
}

And finally some more info: http://www.php.net/~derick/meeting-notes.html#implement-inheritance-rules-for-type-hints

like image 167
Stefan Gehrig Avatar answered Jan 30 '23 07:01

Stefan Gehrig


This seems pretty consistent with most OO principals. PHP isn't like .Net - it doesn't allow you to override class members. Any extension of Foo should slide into where Foo was previously being used, which means you can't loosen constraints.

The simple solution is obviously to remove the type constraint, but if Bar::run() needs a different argument type, then it's really a different function and should ideally have a different name.

If TypeA and TypeB have anything in common, move the common elements to a base class and use that as your argument constraint.

like image 37
Neil E. Pearson Avatar answered Jan 30 '23 07:01

Neil E. Pearson