PHP: Abstract Class and Method

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 contain properties.
Abstract class can contain constants.
Abstract class may not contain any abstract method, it will still be valid abstract class.
Abstract class can contain non abstract methods.
If a class inherits(extends) from an abstract class then it is mandatory for the class to implement all the abstract methods and give their definitions.
Abstract class can inherit from a other abstract classes.
Abstract class can inherit from a non abstract classes.

Abstract Class can not do

Abstract class can not be instantiated.
A child class can only inherit(extend) from one Abstract class(like normal classes).

Abstract Method Capability/Rules

Here are some rules that we have regarding an Abstract Methods-

Abstract Method can do

Any method in an abstract class can be defined as abstract.
In the child class(of abstract class) the method signature should match.
Method defined in the child should match with the number and type of required arguments, with the abstract method signature.
Visibility of abstract method can be Public or Protected.
Visibility of a method can be changed in the child class, as long as the new visibility is less restrictive(more open/accessible).

Abstract Method can not do

Abstract method can not be declared in a non abstract class(normal class).
Abstract method can not be private.

Difference between Abstract Class and Interface

Here are the differences between Abstract and Interface-

Abstract ClassInterface
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”.

Add the “abstract” keyword before the “class” keyword, and the class will be considered as an abstract class.
<?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.

Declare an abstract method by adding “abstract” modifier at the beginning of the function declaration.
Do not write the definition of the function, end the line with a semi-colon (;).
The Abstract method must be inside an Abstract class. We can not declare an Abstract method in a normal class.
<?php

abstract class BigBoxAbs {
    abstract public function myFuncOne();
}
We can define normal methods(with definition) inside an Abstract class.
Child classes(of the Abstract class) do not have to redeclare the methods and those methods can be used by any child class(depending on the visibility of the method).
<?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-

Use the “abstract” keyword to declare a method as abstract.
An abstract method must not include a definition.
The abstract method declaration must end with a semi-colon(;).
<?php

abstract class BigBoxAbs {
    abstract public function myFuncOne();
}
Abstract function can be Public or Protected. As the definition needs to be defined in the child class.
Abstract function can not be Private, and the private method can not be accessed from the child class, and we can not define the method in the child class.
<?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

Use the “extend” keyword to inherit from an abstract class. It works the same way as extending from a normal class.
Make sure to define all the abstract methods in the child 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
An abstract class can contain normal functions.
The normal function can be accessed/used from the child class object, depending on the visibility of the function.
<?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

We can extend an abstract class from another abstract class.
The child abstract child may or may not define the abstract methods declared in the parent abstract class.
It is the responsibility of the normal child class to add definitions of all abstract methods, if there is no definition for the methods yet.
<?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

An abstract class can contain properties like a normal class.
Properties can have any access modifier(Public, Protected, Private), and will be visible depending on the access modifier like it behaves in a normal class.

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

Abstract class can contain constants.
Constants can be of any visibility(public, protected, private), and will be accessible based on the access modifier.
<?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

Method signature of an abstract method should match.
The type and number of arguments should match.
But we can add optional params during the definition in the child class.
<?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

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.