Web Development With HHVM and Hack 13: Classes Part 3: Abstract Classes

Mike Abelar
3 min readApr 20, 2020

--

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

--

--