How to Create a PHP Abstract Class | LoudProgrammer

How to Create a PHP Abstract Class

abstract classes in php

An abstract class in PHP is special because it can not be instantiated. Instead, you typically inherit a set of base functionality from them in a new class. For that reason, they are commonly used as the base classes in a larger class hierarchy.

To better demonstrate this concept, we will create an abstract Animal class and then a Dog class to inherit from the Animal class. In our project, we may very well decide that no one should be able to instantiate the Animal class, because it’s too unspecific, but instead use a specific class inheriting from it. The Animal class will then serve as a base class for our own little collection of animals.

Our Animal class with have some basic properties that describe its attributes like age, hunger, distance covered running, the types of food it can take and the state of joy.

To define an abstract class we begin with the abstract keyword followed by the word class and then the class name. In these examples I have used PHPDoc commenting style to elaborate on the meaning of the code.

/**
 * This abstract class defines a template class for all animals with basic properties and behaviour
 * @author Geoffrey Bans <geoffreybans@gmail.com>
 * @copyright 2016 - 2020 Geoffrey Bans
 * @package Animal
 * @license http://opensource.org/licenses/MIT MIT License
 * @version 0.0.1
 */
abstract class Animal{

	/**
	 * @var int The age of the animal
	 */
	protected $_age;

	/**
	 * @var bool Specifies whether animal is hungry or not
	 */
	protected $_hunger = false;

	/**
	 * @var int The total distance already convered by the animal running
	 */
	protected $_totalDistance = 0;

	/**
	 * @var array The types of foods available for an animal
	 */ 
	protected $_meal = array("fish", "apple");

	/**
	 * @var bool True if the animal has joy
	 */
	protected $_joy = false;

	/**
	 * This constructor instantiates the $_age property
	 * @param int $age The age of the animal
	 * @return void
	 */
	public function __construct($age){
		$this->_age = $age;
	}

	/**
	 * This abstract method defines the animal's communication messages
	 * @param null
	 * @return void
	 */
	abstract public function communicate();

	/**
	 * This method increments the total distance property as the animal is running
	 * If it excedes 500 the animal becomes hungry and unhappy
	 * @param int $distance The distance the animal is running
	 * @return void
	 */
	public function run($distance){

		$this->_totalDistance += $distance;

		if ($this->_totalDistance > 500) {
			
			$this->_hunger = true;
			$this->_joy = false;

		}
	}

	/**
	 * This method feeds the animal if the food requested is available
	 * @param string $meal The name of the food to request
	 * @return void
	 */
	public function feed($meal){

		if (in_array($meal, $this->_meal)) {
			
			$this->_hunger = false;
			$this->_totalDistance = 0;
		}
	}

	/**
	 * This method strokes the animal to make it joyful
	 * @param null
	 * @return void
	 */
	private function stroke(){
		$this->_joy = true;
	}

}

Any class that contains at least one abstract method must also be abstract. Methods defined as abstract simply declare the method’s signature – they cannot define the implementation.

The method “communicate” is an example of an abstract method.

When inheriting from an abstract class, all methods marked abstract in the parent’s class declaration must be defined by the child; additionally, these methods must be defined with the same (or a less restricted) visibility.For example, if the abstract method is defined as protected, the function implementation must be defined as either protected or public, but not private.

Furthermore the signatures of the methods must match, i.e. the type hints and the number of required arguments must be the same. For example, if the child class defines an optional argument, where the abstract method’s signature does not, there is no conflict in the signature.

Extending the class Animal we are going to create a new class Dog and an instance of this class with the following behavior:

  • Dog wants to eat after it runs more than 1000 feet
  • Dog only eats meat
  • Dog says “Waf”
  • Let the dog feel joy :)

First we begin by extending the Animal class using the extends keyword, just as you would do with any regular class.

Since our dog only eats meat, we will need to remove the apples from the array of available foods. We do this by assigning a new value to the $_meal property in the constructor.

/**
 * This class defines a dog instance with the associated properties and behaviour
 * @author Geoffrey Bans <geoffreybans@gmail.com>
 * @copyright 2016 - 2020 Geoffrey Bans
 * @package Animal\Dog
 * @license http://opensource.org/licenses/MIT MIT License
 * @version 0.0.1
 */

class Dog extends Animal {

	/**
	 * This constructor instantiates the $_age and meals properties
	 * @param int $age The age of the animal
	 * @return void
	 */
	public function __construct($age){
		$this->_age = $age;
		$this->_meal = array("fish");
	}

Since this class inherits from the abstract animal class, we have to define the implementation details of the communicate method as it’s an abstract method or PHP would through an error.

	/**
	 * This method expresses the dogs communicaiton message
	 * @param null
	 * @return void
	 */
	public function communicate(){
		echo "Waf";
    }

The Animal class specifies that the animal should need to eat after 500 feet but since our specific Dog implementation requires a minimum of 1000 feet, we have to override the run method definition inherited from the abstract class.

	/**
	 * This method increments the total distance property as the animal is running
	 * If it excedes 1000 the animal becomes hungry and unhappy
	 * @param int $distance The distance the animal is running
	 * @return void
	 */
	public function run($distance){

		$this->_totalDistance += $distance;

		if ($this->_totalDistance > 1000) {
			
			$this->_hunger = true;
			$this->_joy = false;

		}
	}

In order to override a method inherited from an abstract class, we define a method in our child class with the same name as the method we are seeking to override. Therefore, whenever we create an instance of the Dog class, the run method defined in the Dog class would be called instead of the one defined in the abstract class.

Calling the stroke method makes our dog feel joy. But since the definition of the stroke method in the abstract class has a visibility of private, we wont be able to call it from an instance of the class.

Therefore we override the previous implementation specifying a visibility of public so that we can call the method from the object instance.

	/**
	 * This method strokes the animal to make it joyful
	 * @param null
	 * @return void
	 */
	public function stroke(){
		$this->_joy = true;
	}

Let’s now create an instance of Dog class and make it feel joy.

$myDog = new Dog(4);
$myDog->run(1001);
$myDog->feed("fish");
$myDog->communicate();
$myDog->stroke();

Below is the full code for the Dog class.

/**
 * This class defines a dog instance with the associated properties and behaviour
 * @author Geoffrey Bans <geoffreybans@gmail.com>
 * @copyright 2016 - 2020 Geoffrey Bans
 * @package Animal\Dog
 * @license http://opensource.org/licenses/MIT MIT License
 * @version 0.0.1
 */

class Dog extends Animal {

	/**
	 * This constructor instantiates the $_age and meals properties
	 * @param int $age The age of the animal
	 * @return void
	 */
	public function __construct($age){
		$this->_age = $age;
		$this->_meal = array("fish");
	}

	/**
	 * This method expresses the dogs communicaiton message
	 * @param null
	 * @return void
	 */
	public function communicate(){
		echo "Waf";
	}

	/**
	 * This method increments the total distance property as the animal is running
	 * If it excedes 1000 the animal becomes hungry and unhappy
	 * @param int $distance The distance the animal is running
	 * @return void
	 */
	public function run($distance){

		$this->_totalDistance += $distance;

		if ($this->_totalDistance > 1000) {
			
			$this->_hunger = true;
			$this->_joy = false;

		}
	}

	/**
	 * This method strokes the animal to make it joyful
	 * @param null
	 * @return void
	 */
	public function stroke(){
		$this->_joy = true;
	}

}

What do you think about this tutorial and abstracts classes in PHP? Please share your thoughts below.

The following two tabs change content below.
Geoffrey is a lead software developer, author and writer. He writes code from scratch but frequents GitHub. He also writes and talks about technology trends, small business tips and developer productivity hacks. He is no coffee addict.

Leave a Reply

Be the First to Comment!

Notify of
avatar
wpDiscuz