Abstract Class:
Abstract class works as a template for a child class, and the child can build/define functionality based on the abstract class.
An Abstract class is a partially implemented class, as the abstract methods(in the class) do not contain their definition. Those methods are defined in the class that extends the Abstract class.
Abstract class is a class that is declared as abstract, and contains one or more abstract methods.
<?php
abstract class BigBoxAbs {
abstract public function myFuncOne();
public function normalFunc() {
echo 'this is a normal function in ' . __CLASS__ . PHP_EOL;
}
}
Abstract Method:
An abstract method only has the declaration of the method. Only the signature of the method is defined.
abstract public function myFunc();
It does not contain the definition of the method. Instead, it is the responsibility of the class, that extends the abstract class, to implement the definition of the method.
Abstract Class Capability/Rules
Here are some rules that we have regarding an Abstract Classes-
Abstract Class can do
Abstract Class can not do
Abstract Method Capability/Rules
Here are some rules that we have regarding an Abstract Methods-
Abstract Method can do
Abstract Method can not do
Difference between Abstract Class and Interface
Here are the differences between Abstract and Interface-
Abstract Class | Interface |
---|---|
Abstract class can contain non abstract methods(normal method implementations). | Interface can only contain method declaration. |
A class can extend only one Abstract class. | Class can implement multiple interfaces. |
Abstract class can contain Private, Protected, and Public methods. | Interface method declarations in an interface must be Public. |
Abstract class can contain properties(with Public, Private, and Protected visibility). | Interface can not contain property. |
Abstract class can have constructor and/or destructor. | Interface can not contain a constructor or destructor. |
NOTE
We have a full comparison of the Interface, Abstract Class, and trait.
Check the link below for a full comparison-
Abstract Class Declaration
We can declare an abstract class by using the keyword “abstract”.
<?php
abstract class BigBoxAbs {
// This is a valid abstract class declaration
}
NOTE
An Abstract class may or may not contain any abstract method, it is still a valid abstract class.
An empty abstract class is a valid abstract class.
<?php
abstract class BigBoxAbs {
abstract public function myFuncOne();
}
<?php
abstract class BigBoxAbs {
abstract public function myFuncOne();
public function normalFunc() {
echo 'this is a normal function in ' . __CLASS__ . PHP_EOL;
}
}
WARNING
Abstract class can not be instantiated. If we try to instantiate an abstract class like below-
$bigBoxAbs = new BigBoxAbs(); // Error thrown
We will get the following error-
PHP Fatal error:
Uncaught Error: Cannot instantiate abstract class BigBoxAbs
in bigboxcode.php:41
Abstract Method Declaration
Here is how we can define an Abstract method-
<?php
abstract class BigBoxAbs {
abstract public function myFuncOne();
}
<?php
abstract class BigBoxAbs {
abstract private function myFuncOne(); // throws error because of private access modifier
}
WARNING
If an abstract method is declared as private, it throws the following error-
PHP Fatal error: Abstract function BigBoxAbs::myFuncOne()
cannot be declared private
in bigboxcode.php on line 11
Inherit from Abstract Class
<?php
abstract class BigBoxAbs {
abstract public function myFuncOne();
abstract public function myFuncTwo();
public function normalFunc() {
echo 'This is a normal function in ' . __CLASS__ . PHP_EOL;
}
}
class BigBoxChild extends BigBoxAbs {
public function myFuncOne() {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
}
public function myFuncTwo() {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
}
}
// Demo
$bigBoxObj = new BigBoxChild();
$bigBoxObj->myFuncOne();
$bigBoxObj->myFuncTwo();
$bigBoxObj->normalFunc();
Output:
myFuncOne function in BigBoxChild
myFuncTwo function in BigBoxChild
This is a normal function in BigBoxAbs
<?php
abstract class BigBoxAbs {
abstract public function myFuncOne();
abstract public function myFuncTwo();
public function normalFunc() {
echo 'This is a normal function in ' . __CLASS__ . PHP_EOL;
}
}
class BigBoxChild extends BigBoxAbs {
public function myFuncOne() {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
}
}
// Demo
$bigBoxObj = new BigBoxChild();
$bigBoxObj->myFuncOne();
$bigBoxObj->normalFunc();
WARNING
If an abstract method is not defined in the child class, then it throws the following error-
PHP Fatal error: Class BigBoxChild contains 1 abstract method
and must therefore be declared abstract
or implement the remaining methods (BigBoxAbs::myFuncTwo)
in bigboxcode.php on line 12
Abstract Class Inherit from Another Abstract Class
<?php
abstract class BigBoxParentAbs {
abstract protected function myParentFuncA(int $num1, int $num2): int;
abstract public function myParentFuncB();
}
abstract class BigBoxAbs extends BigBoxParentAbs{
abstract public function myFuncOne();
abstract public function myFuncTwo();
public function myParentFuncB() {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
}
public function normalFunc() {
echo 'This is a normal function in ' . __CLASS__ . PHP_EOL;
}
}
class BigBoxChild extends BigBoxAbs {
protected function myParentFuncA(int $num1, int $num2): int {
return $num1 + $num2;
}
public function myFuncOne() {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
echo 'Calculated value from myParentFuncA: ' . $this->myParentFuncA(4, 5) . PHP_EOL;
}
public function myFuncTwo() {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
}
}
// Demo
$bigBoxObj = new BigBoxChild();
$bigBoxObj->myFuncOne();
$bigBoxObj->myFuncTwo();
$bigBoxObj->normalFunc();
$bigBoxObj->myParentFuncB();
Output:
myFuncOne function in BigBoxChild
Calculated value from myParentFuncA: 9
myFuncTwo function in BigBoxChild
This is a normal function in BigBoxAbs
myParentFuncB function in BigBoxAbs
NOTE
If a class inherits from an abstract class, and that abstract class inherits from another abstract class, then it is the responsibility of the class to define all abstract methods(which are not defined yet).
Abstract Class Inherit from Non-Abstract Class
An abstract class can extend from a normal non-abstract class. Check the example below-
<?php
class BigBoxParent {
protected function myParentFuncA(int $num1, int $num2): int {
return $num1 + $num2;
}
public function myParentFuncB() {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
}
}
abstract class BigBoxAbs extends BigBoxParent{
abstract public function myFuncOne(): void;
abstract public function myFuncTwo(): void;
public function normalFunc() {
echo 'This is a normal function in ' . __CLASS__ . PHP_EOL;
}
}
class BigBoxChild extends BigBoxAbs {
public function myFuncOne(): void {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
echo 'Calculated value from myParentFuncA: ' . $this->myParentFuncA(4, 5) . PHP_EOL;
}
public function myFuncTwo(): void {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
}
}
// Demo
$bigBoxObj = new BigBoxChild();
$bigBoxObj->myFuncOne();
$bigBoxObj->myFuncTwo();
$bigBoxObj->normalFunc();
$bigBoxObj->myParentFuncB();
Output:
myFuncOne function in BigBoxChild
Calculated value from myParentFuncA: 9
myFuncTwo function in BigBoxChild
This is a normal function in BigBoxAbs
myParentFuncB function in BigBoxParent
Abstract Class with Properties
We can declare properties in an abstract class like below-
<?php
abstract class BigBoxAbs {
public string $myStrProp;
protected int $myIntProp;
private array $myArr;
}
Or we can do it by using property promotion in the constructor. Check the example below-
<?php
abstract class BigBoxAbs {
public function __construct(
public string $myStrProp,
protected int $myIntProp,
private array $myArr) {
}
abstract public function myFuncOne();
public function normalFunc() {
echo 'this is a normal function in ' . __CLASS__ . PHP_EOL;
echo 'Value of $myArr: ' . implode(',', $this->myArr) . PHP_EOL;
}
}
class BigBoxChild extends BigBoxAbs {
public function myFuncOne() {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
// Access Public and Protected properties of Abstract class
echo 'Value of $myStrProp: ' . $this->myStrProp . PHP_EOL;
echo 'Value of $myIntProp: ' . $this->myIntProp . PHP_EOL;
}
}
// Demo
$bigBoxObj = new BigBoxChild("Big Box Str", 1001, [1, 1, 2, 3, 5, 8]);
$bigBoxObj->myFuncOne();
$bigBoxObj->normalFunc();
Output:
myFuncOne function in BigBoxChild
Value of $myStrProp: Big Box Str
Value of $myIntProp: 1001
this is a normal function in BigBoxAbs
Value of $myArr: 1,1,2,3,5,8
Abstract Class with Constants
<?php
abstract class BigBoxAbs {
public const MY_STR_C = "Big Box Str Constant";
protected const MY_INT_C = 1001;
private const MY_ARR_C = [1, 1, 2, 3, 5, 8, 13, 21];
abstract public function myFuncOne();
public function normalFunc() {
echo 'This is a normal function in ' . __CLASS__ . PHP_EOL;
echo 'Value of MY_ARR_C: ' . implode(',', self::MY_ARR_C) . PHP_EOL;
}
}
class BigBoxChild extends BigBoxAbs {
public function myFuncOne() {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
echo 'Value of MY_STR_C: ' . BigBoxAbs::MY_STR_C . PHP_EOL;
echo 'Value of MY_INT_C: ' . BigBoxAbs::MY_INT_C . PHP_EOL;
}
}
// Demo
$bigBoxObj = new BigBoxChild();
$bigBoxObj->myFuncOne();
$bigBoxObj->normalFunc();
Output:
myFuncOne function in BigBoxChild
Value of MY_STR_C: Big Box Str Constant
Value of MY_INT_C: 1001
This is a normal function in BigBoxAbs
Value of MY_ARR_C: 1,1,2,3,5,8,13,21
Constants can be overridden in the child class-
<?php
abstract class BigBoxAbs {
public const MY_STR_C = "Big Box Str Constant";
protected const MY_INT_C = 1001;
private const MY_ARR_C = [1, 1, 2, 3, 5, 8, 13, 21];
abstract public function myFuncOne();
public function normalFunc() {
echo 'This is a normal function in ' . __CLASS__ . PHP_EOL;
echo 'Value of MY_ARR_C: ' . implode(',', self::MY_ARR_C) . PHP_EOL;
}
}
class BigBoxChild extends BigBoxAbs {
public const MY_STR_C = "Changed in the child";
protected const MY_INT_C = 9999;
public function myFuncOne() {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
echo 'Value of MY_STR_C: ' . static::MY_STR_C . PHP_EOL;
echo 'Value of MY_INT_C: ' . static::MY_INT_C . PHP_EOL;
}
}
// Demo
$bigBoxObj = new BigBoxChild();
$bigBoxObj->myFuncOne();
$bigBoxObj->normalFunc();
Output:
myFuncOne function in BigBoxChild
Value of MY_STR_C: Changed in the child
Value of MY_INT_C: 9999
This is a normal function in BigBoxAbs
Value of MY_ARR_C: 1,1,2,3,5,8,13,21
Abstract Method Signature Matching
<?php
abstract class BigBoxAbs{
abstract public function myFuncOne(int $param1, float $param2): float;
abstract public function myFuncTwo(int $a,
int $b,
string $optional1 = "Big Box",
array $optional2 = []): void;
// There are not parameter defined for this method
abstract public function myFuncThree(): void;
}
class BigBoxChild extends BigBoxAbs {
public function myFuncOne(int $param1, float $param2): float {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
return $param1 * $param2;
}
public function myFuncTwo(int $a,
?int $b = 100,
?string $optional1 = null,
?array $optional2 = []): void {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
}
// We can add optional methods here
public function myFuncThree(int $opt1 = 10, int $opt2 = 99): void {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
echo 'Value of $opt1: ' . $opt1 . PHP_EOL;
echo 'Value of $opt2: ' . $opt2 . PHP_EOL;
}
}
// Demo
$bigBoxObj = new BigBoxChild();
$bigBoxObj->myFuncOne(1, 2);
$bigBoxObj->myFuncTwo(3);
$bigBoxObj->myFuncThree();
$bigBoxObj->myFuncThree(199);
$bigBoxObj->myFuncThree(300, 500);
Output:
myFuncOne function in BigBoxChild
myFuncTwo function in BigBoxChild
myFuncThree function in BigBoxChild
Value of $opt1: 10
Value of $opt2: 99
myFuncThree function in BigBoxChild
Value of $opt1: 199
Value of $opt2: 99
myFuncThree function in BigBoxChild
Value of $opt1: 300
Value of $opt2: 500
NOTE
We can use optional parameters during the definition of the method in the child class.
Abstract Method Visibility Change
We can change the visibility of the methods in the child class.
We can change the visibility to a more open one. Like from Protected to Public.
Can not make is more restricted.
<?php
abstract class BigBoxAbs{
abstract public function myFuncOne(int $param1, float $param2): float;
// This method is protected here
abstract protected function myFuncTwo(): void;
}
class BigBoxChild extends BigBoxAbs {
public function myFuncOne(int $param1, float $param2): float {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
return $param1 * $param2;
}
// Changed to public
public function myFuncTwo(): void {
echo __FUNCTION__ . ' function in ' . __CLASS__ . PHP_EOL;
}
}
// Demo
$bigBoxObj = new BigBoxChild();
$bigBoxObj->myFuncOne(1, 2);
$bigBoxObj->myFuncTwo();
Output:
myFuncOne function in BigBoxChild
myFuncTwo function in BigBoxChild