PHP Type Hinting
In the last chapter, we have seen the PHP type hinting for arrays and objects. In this chapter, we will see how in some situations object type hinting would not work, and then, in that case, we can use abstract class or interface type hinting.
The PHP Type hinting for the interface will work exactly the same for both abstract class and interface. In this tutorial, let’s see this topic in detail with the example.
Let’s say a mobile shop is selling mobile phones of different models.
From time to time, the shop is offering a discount on mobiles for its customers. Shop hires you to build a program to calculate the discounted price while selling a mobile.
And the discount will change as per the model of mobiles.
From this information, you created classes for each mobile model to calculate the discount for each mobile model.
You created the first class “Apple” for Apple mobiles like this:
<?php class Apple { private $model; private $price; public function __construct($model,$price) { $this->model = $model; $this->price = $price; } public function getPrice() { return $this->price; } } ?>
And then you created the class “Discount” to calculate a discounted price as per the discount percentage given for each mobile model, like this:
<?php class Discount { public function discountPrice(Apple $apple, $discountPercent) { echo $apple->getPrice() - 100 * ($discountPercent/100); } } ?>
The Discount class has a single method “discountPrice” which currently has two arguments, first is an object of Apple class and second is a discount amount.
As you see in the “discountPrice” method I have applied an object type hinting which will currently allow only “Apple” type of object.
Now let’s try to calculate the discounted price for an Apple mobile with a price say Rs. 40000 and with a discount of Rs. 1000, using a “Discount” class.
$apple = new Apple('IphoneX', 40000); $disc = new Discount(); $disc->discountPrice($apple,1000);
Above you have created a new Apple class object and a Discount class object. Then an Apple class object is passed to the Discount object’s method discountPrice with an amount to deduct i.e. 1000.
And the output generated will be:
Discounted price for IphoneX is = 39000
So, the above program developed by you is working fine for the Apple class object.
Now you want to calculate a discounted price for a Samsung mobile with Rs. 2000 as a discount.
Let’s do the same process by creating a “Samsung” class and passing the Samsung class object to the Discount class.
PHP type hinting: Creating a Samsung class:
<?php class Samsung { private $model; private $price; public function __construct($model,$price) { $this->model = $model; $this->price = $price; } public function getModel() { return $this->model; } public function getPrice() { return $this->price; } } ?>
Now you tried to pass an object of a Samsung class with its price say Rs. 30000 and a discount amount of Rs. 2000 to the Discount class object’s method “discountPrice” like the below code.
$samsung = new Samsung('Galaxy', 30000); $disc = new Discount(); $disc->discountPrice($samsung,1000);
Now at this time, the program will generate a fatal error like this – “Fatal error: Uncaught TypeError: Argument 1 passed to Discount::discountPrice() must be an instance of Apple, an instance of Samsung given, “.
This error is generated because you are trying to send the Samsung class object to the Apple class object argument in a “discountPrice(Apple $apple, $discountAmount)” function.
Then what will you do?
In this case, you may think of changing a type hinting inside discountPrice method from Apple to Samsung.
But let’s say there are other mobile models also present in a shop, like “RedMi“, “Nokia“, “LG“, etc.
Then will it be feasible to manually change the code of discountPrice method for each mobile model?
No, this will be a bad solution. So how can we solve the problem that arises due to object type hinting in this case?
Yes, the solution is interface type hinting.
Let’s see how can we do interface type hinting in the PHP type hinting concept.
Creating an abstract class: PHP Type Hinting
Let’s create an abstract class “Mobile” for both types of mobile models. You can learn more about abstract class and interface in our previous tutorials.
At this time you created an abstract class Mobile which will have common properties and methods for all the mobile models.
And then extends the abstract Mobile class into the Apple and Samsung class.
Then the program would look like this:
<?php abstract class Mobile { protected $model; protected $price; public function getModel() { return $this->model; } public function getPrice() { return $this->price; } } class Apple extends Mobile { public function __construct($model,$price) { $this->model = $model; $this->price = $price; } } class Samsung extends Mobile { public function __construct($model,$price) { $this->model = $model; $this->price = $price; } } ?>
Now update the “discountPrice” method.
Just change object type hinting from the class name “Apple” to an abstract class name “Mobile” inside discountPrice method.
Also, change the name of the object argument variable from specific “$apple” to a generalized “$mobile”. And update $mobile inside a method body.
Now the discountPrice method inside a Discount class will look like this:
class Discount { function discountPrice(Mobile $mobile, $discountAmount) { echo "<br>Discounted price for ".$mobile->getModel()." is = "; echo $mobile->getPrice() - $discountAmount; } }
As you see we have changed type hinting from a concrete class Apple to an abstract class Mobile.
This will comes under an interface type hinting.
Now let’s try to send both Apple class and Samsung class objects one by one to the discountPrice method to calculate the discounted price.
$apple = new Apple('IphoneX', 40000); $samsung = new Samsung('Galaxy', 30000); $disc = new Discount(); $disc->discountPrice($apple,1000); $disc->discountPrice($samsung,2000);
The output will be:
Discounted price for IphoneX is = 39000 Discounted price for Galaxy is = 28000
As you see now, your program is accepting both the class objects in the same discountPrice method without any error.
Here we have used an abstract class as there are few common methods with general functionality present. You can also use an interface for the same purpose in PHP Type Hinting.
The use of an abstract class or an interface will make the program very flexible. This removes the dependence of one particular class in a method to all types of classes which extends a Mobile class.
Here interface type hinting makes the method to accept all types of mobile instead of just one Apple mobile.
The same type of functionality is used in another programming concept called dependency injection, which is one of the very useful design patterns.
Hope you will get a clear picture of what is interface type hinting along with array and object type hinting in these PHP type hinting tutorials.