In PHP we can type hint function arguments since version 5.0. Over the years and with newer versions of PHP the number of possible type hints have increased. Here’s an overview:
Since PHP 5.0 we’ve been able to type hint function arguments and since PHP 7.0 we’re aso able to type hint scalar values. The entire set of type hints can be used for function return type hinting since version 7.0 as well. Let’s take a closer look at self
and parent
. They’ve been around for a long time
but we don’t see them very often. Why is that?
self
Self means: an object of the same type (the current class or a subclass). Every variable passed must be an instanceof
the same class.
Function argument type
When modelling relations between nodes/objects/…, it happens that a relationship needs to be modelled between two objects of the same type. In this case it’s useful to use the self
type hint.
When you create an implementation of this interface (or when overwriting this in case of less SOLID designed code) it will be necessary to replace the self
type hint with the original class/interface name.
Return type
Let’s take a look in what situations we can use self
as a return type.
Mutators
One of the more obvious use case is setters (or mutators) that allow method chaining.
setBar($bar)->setBaz($baz);
If you use self
return type it doesn’t matter if the method returns a cloned version of the object (this is the case when you’re dealing with immutable objects). The object that is returned is of the same type as the object on which the method is called.
When extending or implementing a method in a subclass you have to make type hint explicit so that declaration is compatible.
If you use this object it will tell your IDE that whatever is returned will be of type Foo
(the interface). So practically it won’t/shouldn’t autocomplete method names of the Foo implementing class anymore.
setBar(new Bar())->setBaz(new Baz());
In the example above, if setBaz
is not a method of the interface Foo
, it will not be recognized by the IDE. Thus for chaining methods, the return type self
isn’t so useful.
Prior to PHP 7.0 we usually only declared return types in the docblocks with @return $this
, @return self
or @return static
.
For chained methods I still use @return static
and @return $this
in the docblocks.
Factory methods
It’s not easy to come up with examples of non-setter methods that still return objects of the same class. Here’s one:
An implementation would be:
I’m not saying this is good design, though. This method clearly doesn’t belong in this interface. There are better factory-like methods that can have a self
return type hint. I just can’t come up with a practical one at this moment. Feel free to suggest an example in the comments below.
parent
I noticed from the PHP docs that parent
is a valid type hint. Let me explain what parent
means in the context of type hinting:
parent
always refers to the class that you are extending. Thus in the example above it means: Bar, or one of its subclasses. The object that gets passed here could be of a sibling class of Foo, for example.
The type hint can not refer to an interface. It’s exactly the same as when you would call a method on a parent class (parent::__construct
for example). You can only use that when the current class actually extends a parent class.
There are a couple of reasons why the parent
type hint isn’t used much:
When your code’s design respects the SOLID principles, it should strike you that almost everything is either an interface or an implementing class (leaf node in inheritance tree). You’ll see that the number of abstract classes will be very small and almost no classes get extended. So using the parent
type hint is not that useful, except in some very rare cases.
Secondly, it is generally better to type hint interfaces. This again is part of the SOLID design principles: Liskov Substitution Principle (objects should be replaceable with objects of subtypes), Interface Segregation Principle and Dependency Inversion Principle (Depend upon abstractions(interfaces)). Thus, again: the amount of type hints that are class type hints and not interface type hints is very small.
If you’re having questions or would like to add something, feel free to leave a comment below.
Cheers!
Other interesting reads:
- The easiest production-ready image to run your Laravel application
- A few things you should know to nail your next job interview
- How to assist your product marketing team as a software engineer
In PHP we can type hint function arguments since version 5.0. Over the years and with newer versions of PHP the number of possible type hints have increased. Here’s an overview:
Since PHP 5.0 we’ve been able to type hint function arguments and since PHP 7.0 we’re aso able to type hint scalar values. The entire set of type hints can be used for function return type hinting since version 7.0 as well. Let’s take a closer look at self
and parent
. They’ve been around for a long time
but we don’t see them very often. Why is that?
self
Self means: an object of the same type (the current class or a subclass). Every variable passed must be an instanceof
the same class.
Function argument type
When modelling relations between nodes/objects/…, it happens that a relationship needs to be modelled between two objects of the same type. In this case it’s useful to use the self
type hint.
When you create an implementation of this interface (or when overwriting this in case of less SOLID designed code) it will be necessary to replace the self
type hint with the original class/interface name.
Return type
Let’s take a look in what situations we can use self
as a return type.
Mutators
One of the more obvious use case is setters (or mutators) that allow method chaining.
setBar($bar)->setBaz($baz);
If you use self
return type it doesn’t matter if the method returns a cloned version of the object (this is the case when you’re dealing with immutable objects). The object that is returned is of the same type as the object on which the method is called.
When extending or implementing a method in a subclass you have to make type hint explicit so that declaration is compatible.
If you use this object it will tell your IDE that whatever is returned will be of type Foo
(the interface). So practically it won’t/shouldn’t autocomplete method names of the Foo implementing class anymore.
setBar(new Bar())->setBaz(new Baz());
In the example above, if setBaz
is not a method of the interface Foo
, it will not be recognized by the IDE. Thus for chaining methods, the return type self
isn’t so useful.
Prior to PHP 7.0 we usually only declared return types in the docblocks with @return $this
, @return self
or @return static
.
For chained methods I still use @return static
and @return $this
in the docblocks.
Factory methods
It’s not easy to come up with examples of non-setter methods that still return objects of the same class. Here’s one:
An implementation would be:
I’m not saying this is good design, though. This method clearly doesn’t belong in this interface. There are better factory-like methods that can have a self
return type hint. I just can’t come up with a practical one at this moment. Feel free to suggest an example in the comments below.
parent
I noticed from the PHP docs that parent
is a valid type hint. Let me explain what parent
means in the context of type hinting:
parent
always refers to the class that you are extending. Thus in the example above it means: Bar, or one of its subclasses. The object that gets passed here could be of a sibling class of Foo, for example.
The type hint can not refer to an interface. It’s exactly the same as when you would call a method on a parent class (parent::__construct
for example). You can only use that when the current class actually extends a parent class.
There are a couple of reasons why the parent
type hint isn’t used much:
When your code’s design respects the SOLID principles, it should strike you that almost everything is either an interface or an implementing class (leaf node in inheritance tree). You’ll see that the number of abstract classes will be very small and almost no classes get extended. So using the parent
type hint is not that useful, except in some very rare cases.
Secondly, it is generally better to type hint interfaces. This again is part of the SOLID design principles: Liskov Substitution Principle (objects should be replaceable with objects of subtypes), Interface Segregation Principle and Dependency Inversion Principle (Depend upon abstractions(interfaces)). Thus, again: the amount of type hints that are class type hints and not interface type hints is very small.
If you’re having questions or would like to add something, feel free to leave a comment below.
Cheers!
Other interesting reads:
- The easiest production-ready image to run your Laravel application
- A few things you should know to nail your next job interview
- How to assist your product marketing team as a software engineer
Member discussion