Skip to main content

Why use abstract classes when method overriding can achieve the same functionality in php?

Created
Active
Viewed 398 times
3 replies
4

I’m trying to understand the practical importance of abstract classes in object-oriented programming, particularly in PHP.

From my understanding, abstract classes enforce child classes to implement specific abstract methods, which ensures some consistency. However, I feel like we could achieve the same functionality using method overriding.

For example, by simply overriding methods in the child classes, I could customize the behavior for each class without needing to enforce anything through abstract methods. This would result in slightly more code but would allow greater flexibility.

So,

Q1. what’s the unique purpose of abstract classes that can’t be achieved with just method overriding?

Q2. Why is it important for abstract classes to enforce abstract methods in child classes?

Q3. Is this enforcing thing is for developer who is developing the app or its enforcing some restriction on end user so that user wont be able to do his/her wishful thing like adding some user in some other category (which is restricted by our hard code)while giving access control to existing user where everything is handled dynamically?

If someone could explain this with a practical example or use case, that would help me understand better.

3 replies

Sorted by:
79352328
2
  • 5.1k
  • 1
  • 18
  • 26

An abstract class without an interface is useless in most use cases. An interface defines the methods to include wether in an abstract class or in a child class, which inherits from the abstract class. An abstract class CAN but MUST NOT implement methods, that are defined in an interface. If so you can declare implementend methods as abstract, if you want to force child classes to implement logic for abstract declared methods.

The most forward point of abstract classes is central logic, that can be used by all child classes. If an interface defines a method `doSomething(string $bla, in4 $yadda): void` you can defined the logic in an abstract class. This central logic can be used by all children extending this abstract class. If you want to say so, abstract classes define functionality, that is used by all children. They 're not working as a method template. That 's the job of an interface. An abstract class contains logic, which is relevant for every child.

Question 2:
As described above, this is not an essential point of abstract classes. They merely work as an abstraction layer in cooperation with an interface, which contains functionality that is the same for all child classes. You can specify abstractly declared methods for child classes. But you do not have to. This is particularly important to avoid having to write code multiple times.

Question 3:
Normally, abstract classes and interfaces don't force you to do anything. They only require you to write clean, structured code. Child classes can use methods that have been defined via an interface or an abstract class. However, they do not have to be used. You are still free not to implement an interface or an abstract class. In most cases, however, not implementing them has more disadvantages than advantages. Think of logic, that checks for existence of an implemented interface.

Long story short: Abstraction is a good thing in software development. If it feels like an abstraction is limiting you, you might want to rethink your logic.

79361646
2

Q1. Making a class abstract allows you to implement common logic in the base class while preventing this base class being instantiated itself. If you only used overriding than someone can make instance of base class which might not contain complete implementation of logic.

Q2. Abstract methods allow base class to call these methods (because it knows their definitions) while delegating concrete implementation of these methods to child classes.

An example: You are developing an REST API connection and you have classes representing different requests. One of methods in those classes is a method that returns path to endpoint. The interface of the request classes might look like this:

interface ApiRequestInterface
{
    public function getPath(): string;
}

Then you have abstract base class, that knows common part of path of endpoint but doesn't know which collection the request will be accessing:

abstract class RequestBase implements ApiRequestInterface
{
    abstract protected function collection(): string;

    public function getPath(): string
    {
        return '/api/v1/' . $this->collection();
    }
}

And then you have class representing specific api request:

class GetBooksRequest extends RequestBase
{
    protected function collection(): string
    {
        return 'books';
    }
}

Of course, even in this case you could make RequestBase non-abstract with collection() as empty method. But if you do then doing something like this $request = new RequestBase() will be ok, but sending request like that won't work and you will have to look for cause. If the RequestBase is abstract trying to create an instance of it will result in error. And you will know where the problem is right away.

79365654
1

I think this question is plain incorrect. What is functionality? You confuse the functionality of the software product developed with PHP with the functionality of PHP as a development tool.

Let's say, you successfully develop a project and then remove abstract words. The runtime functionality will remain exactly the same. But the code base and further development and support of that code base as the human activity will not be the same. It will become worse, because abstract is yet another way to protect the developers from writing something wrong.

I also want to bring to your attention that PHP is not a compiled language. It means that the overriding mechanism is not the real overriding found in compiler-based OOP. Basically, everything is less efficient compared to compiled languages, both runtime and development practice.

Finally, let's see:

I could customize the behavior for each class without needing to enforce anything through abstract methods. This would result in slightly more code but would allow greater flexibility.

I think this is also wrong. But I can imagine that I've missed something. In this case, I would like you to demonstrate a single case where you can achieve any greater flexibility without abstract. So far, I think that you cannot add any flexibility by eliminating abstract.