Web Development With HHVM and Hack 14: Classes Part 4: Generics
In the last tutorial, we went over abstract classes: https://medium.com/@mikeabelar/web-development-with-hhvm-and-hack-13-classes-part-3-ae319f4496da. In this tutorial, we will go over using generics.
What Are Generics?
Sometimes in classes, you will want the same functionality but for different data types. Take the example of a class that has multiple ways of displaying a message. The message is a string. Below is an implementation of the class:
class DisplayClass {
private string $message;public function __construct(string $message) {
$this->message = $message;
}public function printTwice() : void {
print($this->message . "\n");
print($this->message . "\n");
}public function printThrice() : void {
print($this->message . "\n");
print($this->message . "\n");
print($this->message . "\n");
}public function setDifferentMessage(string $new_message) : void {
$this->message = $new_message;
}
}
In this class, we take in a string that serves as our message. We then have functions for printing this message 2 and 3 times. Finally, we have a function to change the current message. However, what if instead of message
being a string, I wanted my message to be an integer? In order to do that, I would need to define a new class as my current class only takes in string parameters. However, using generics, we can accomplish this with just one class. Generics allow us to declare a type when we create an instance of the class. That type is then used throughout the whole life of the class.
DisplayClass using Generics
Below is the code that helps us use integers instead of strings for the DisplayClass. This DisplayClass below uses generics:
// Notice <T> that we add after class name
class DisplayClass<T> {
// replace string with T
private T $message;
// again, replace string with T
public function __construct(T $message) {
$this->message = $message;
}public function printTwice() : void {
print($this->message . "\n");
print($this->message . "\n");
}public function printThrice() : void {
print($this->message . "\n");
print($this->message . "\n");
print($this->message . "\n");
}public function setDifferentMessage(T $new_message) : void {
$this->message = $new_message;
}
}<<__EntryPoint>>
function main() : noreturn {
// we define the type of the class along with the parameter
$class_string = new DisplayClass<string>("ay");
$class_string->printThrice();
// a different type of instance
$class_int = new DisplayClass<int>(5);
$class_int->printThrice();
exit(0);
}
The output produces:
ay
ay
ay
5
5
5
Let us look at what we changed. First, right after the class declaration, we type <T>
which signifies that when we declare the class, we are expecting a type parameter, which will be called T
within the class. Then, for every previous instance of string
, we just replace string
with T
. That is it.
Now, when we create an instance of the class, we pass the value of T in angled brackets along with the parameter. Therefore, we can now see how we arrived at our output above. The class_string
instance uses a string while the class_int
instance uses an integer.
In the next tutorial, we cover static functions: https://medium.com/@mikeabelar/web-development-with-hhvm-and-hack-15-classes-part-5-33ae586a2f9d