Web Development With HHVM and Hack 13: Classes Part 3: Abstract Classes
In the last tutorial, we explored interfaces: https://medium.com/@mikeabelar/web-development-with-hhvm-and-hack-13-classes-part-2-4a6d2d96597f. In this tutorial, we will explore abstract classes.
What are Abstract Classes?
Abstract classes are like interfaces, except you can provide a default implementation of a function in an abstract class, whereas, in an interface, you cannot provide any implementation for any function.
An Example
Let us consider the example from the last tutorial where we had a Person
interface and two classes that implemented the interface: PersonA
and PersonB
. Both classes had to implement a sayGreeting()
function. To illustrate abstract classes, we will consider the same setup but now consider a new function which is added to the Person
class: sayLanguage()
. To explore this example, create a new folder for this tutorial. Inside the folder, do touch .hhconfig
and then touch abstract.hack
. Then, paste the following contents inside abstract.hack
:
// we define a class to be abstract with the abstract keyword
abstract class Person {
// any function we do not want to implement, we declare abstract
// public abstract function sayGreeting(): void;
// define a function normally
public function sayLanguage() {
print("English\n");
}
}
// now we use the word extends instead of implements
class PersonA extends Person {
// now we define the function
public function sayGreeting(): void {
print("Hi! I am Person A!\n");
}
}
class PersonB extends Person {
// now we define the function
public function sayGreeting(): void {
print("Hi! I am Person B!\n");
}
}
<<__EntryPoint>>
function main(): noreturn {
$personA = new PersonA();
$personB = new PersonB();
$personA->sayGreeting();
$personB->sayGreeting();
$personA->sayLanguage();
$personB->sayLanguage();
exit(0);
}
Then, run the program hhvm abstract.hack
to get the following output:
Hi! I am Person A!
Hi! I am Person B!
English
English
Let us discuss what is different with abstract classes. First, the declaration of the class uses abstract class
instead of interface
. Second, for any function we do not wish to implement, we use the abstract
keyword. Any function that we do wish to implement is just done so. Third, we use extends
rather than implements
when dealing with classes that use abstract classes.
Note: We cannot create an instance of an abstract class by itself. We can only create an instance of a class that extends an abstract class.
Looking at the output, we see that the output of thesayGreeting
function is different because we defined it to be different. We also see that the sayLanguage
function does output the same message as both classes use the same default implementation.
Now say we want to change the default implementation of sayLanguage.
How would we do that? Below is an example:
// we define a class to be abstract with the abstract keyword
abstract class Person {
// any function we do not want to implement, we declare abstract
// public abstract function sayGreeting(): void;
// define a function normally
public function sayLanguage() {
print("English\n");
}
}
// now we use the world extends instead of implements
class PersonA extends Person {
// now we define the function
public function sayGreeting(): void {
print("Hi! I am Person A!\n");
}
public function sayLanguage() {
print("Spanish\n");
}
}
class PersonB extends Person {
// now we define the function
public function sayGreeting(): void {
print("Hi! I am Person B!\n");
}
}
<<__EntryPoint>>
function main(): noreturn {
$personA = new PersonA();
$personB = new PersonB();
$personA->sayGreeting();
$personB->sayGreeting();
$personA->sayLanguage();
$personB->sayLanguage();
exit(0);
}
Which outputs:
Hi! I am Person A!
Hi! I am Person B!
Spanish
English
All we do is redefine the function in the class that extends the abstract class as seen with the PersonA
class.
In the next tutorial, we cover generics: https://medium.com/@mikeabelar/web-development-with-hhvm-and-hack-14-classes-part-4-f97851b1023c