Starting with PHP 7.4, you can specify contravariant parameter types in your class methods. This means that the parameter types can be widened (i.e. made less specific) when overriding the parameter types of the parent method.
In PHP, a type declaration is considered less specific when you:
- Add a type to a union type;
- Removing a type from an intersection type;
- Change a child class type to a supertype;
- Change
array
orTraversable
toiterable
; - Widen a type to be untyped.
Please note the following:
- It is type safe to allow an overriding method to accept a more general parameter type than the method in the base class;
- PHP does not support contravariance for the
callable
parameter type; - Contravariance rules also work on parameter types specified in
interface
methods.
Adding a Type to a Union Type
You can widen child method's parameters when overriding the parent method by adding a type to an existing union type or by creating a union type. This will make the type less specific. For example:
// PHP 8+ class A { public function foo(string|int $arg) { // ... } } class B extends A { public function foo(string|int|float $arg) { // ... } }
Removing a Type From an Intersection Type
You can widen child method's parameters when overriding the parent method by removing a type from an existing intersection type. This will make the type less specific. For example:
// PHP 8.1+ class A { public function foo(Bar&Qux $arg) { // ... } } class B extends A { public function foo(Bar $arg) { // ... } }
Changing a Child Class Type to a Supertype
You can specify a supertype of the parameter defined in the parent method's parameter in the child that overrides it. This would widen the parameter type. For example:
// PHP 7.4+ class A { public function foo(stdClass $obj) { // ... } } class B extends A { public function foo(object $obj) { // ... } }
In the example above you can see how the B::foo()
method specifies a less specific parameter type than its parent, of type object
(which is a supertype of stdClass
).
Changing array
or Traversable
to iterable
Parameter types of array
or the Traversable
interface can be widened in an overriding child method by specifying iterable
as the parameter type. For example:
// PHP 7.4+ class A { public function foo(array $collection) { // ... } } class B extends A { public function foo(iterable $collection) { // ... } }
// PHP 7.4+ class A { public function foo(Traversable $obj) { // ... } } class B extends A { public function foo(iterable $obj) { // ... } }
Widening a Type to be Untyped
You may widen a parameter type to accept any type of value by making the parameter untyped in the overriding child method. For example:
// PHP 7.4+ class A { public function foo(string $value) { // ... } } class B extends A { public function foo($value) { // ... } }
This post was published (and was last revised ) by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.