简体   繁体   中英

PHP: what is the use case of abstract class

As per php.net documentation :

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, ie 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. This also applies to constructors as of PHP 5.4. Before 5.4 constructor signatures could differ.

In php.net they have shown the following example:

abstract class AbstractClass
{
    // Force Extending class to define this method
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // Common method
    public function printOut() {
        print $this->getValue() . "\n";
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";

If I run this I get the below output:

ConcreteClass1 FOO_ConcreteClass1 ConcreteClass2 FOO_ConcreteClass2

Reading the documentation, my initial understanding was "parent classes in general can not access methods from their children if they are extend" and that's why we need abstract classes. However, when I tried the same example above with a little bit of tweak, removing all the abstractions (given below) I see the exact same output as the previous example. Therefore, why do we need abstract classes in PHP. Only use case I found is while implementing an interface in the parent class; I get error if I do not declare the parent as abstract. Is there other cases where I must or it is highly recommended to use abstract class?

//abstract
class AbstractClass
{
    // Force Extending class to define this method
    //abstract protected function getValue();
    //abstract protected function prefixValue($prefix);

    // Common method
    public function printOut() {
        print $this->getValue() . "\n";
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";

If I have a group of similar things, let's say furniture.

class Chair extends Furniture {
    // define methods to handle being sat on
}
class Table extends Furniture {
    // define methods to handle holding things up
}

And so on. But "Furniture" is an abstract concept. It is not, itself, a thing the way "Chair" and "Table" are. Therefore, it would be best to define:

abstract class Furniture {
    // define methods that apply to all kinds of furniture
}

It's always a good idea to think of classes as "types of thing". Some are concrete, like chairs and tables, and others are abstract, like furniture.

The point is, it makes no sense to have new Furniture() in your code, because furniture should be a specific kind. Using abstract class disallows new Furniture() and acts as a sanity check.

However, when I tried the same example above with a little bit of tweak, removing all the abstractions (given below) I see the exact same output as the previous example.

PHP is dynamically typed so the parent class can access methods that 'may or may not exist' 1 ; the same polymorphism still holds (for non-private methods). In a languages like Java or C#, the code would have failed to compile. (Interface/contract checking is a separate issue 2 .)

Thus both examples are technically valid in PHP and will produce the same output, without error or warning.

Is there other cases where I must or it is highly recommended to use [abstract methods]?

It is 'more correct' when applying nominative types / class declarations to annotate the method as abstract as this:

  • Establishes a guarantee that an implementation is provided by concrete subclasses 2

  • Provides additional information for type-checking tools; and is a safeguard if stricter type checking is applied in the future

  • Declares a method signature and documentation stub; and appears in type reflection

The linked example/documentation already explain the semantic goal of abstract methods. (However it is fraught with some .. questionable wording; eg. private methods cannot be abstract .)


1 This is also known as duck typing and is allowed in many other dynamic languages - including Ruby, Python, and JavaScript - which support OO and and the same concept of abstract methods, albeit less formally, as expressed through subtype polymorphism .

2 Interface/contract checking (which is only done for type definitions) ensures that the implementing class, or subclass for abstract classes, must conform to the specified types. In the case of abstract methods this means that subclasses must provide method implementations or be abstract themselves .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM