Abstract class represents a new data type in your application. Classes define a blueprint for the objects, and we know how to use these objects of the certain class type. Just like we know how to use strings and arrays. When we extend one class from another, we create a new sub-type. According to Liskov Substitution Principle, we can use these sub-types without any special knowledge, only by reading the parent class public interface.
Cache class hierarchy:
All of these classes should behave as a parent
Interface describe an aspect of a type. In PHP we don’t have multiple inheritance, but we can implement many interfaces. According to Interface Segregation Principle, interfaces should be small and specific. In the context of the previous example, let’s define an interface for the objects, that can be cached
We can notice that many interfaces are usually named in a common way. They usually end with able or ing. And furthermore, interfaces can be implemented in entirely different types, which doesn’t have anything in common. In the example above, we two different classes
Product, but they both implement one interface and can be used by
Cache class interchangeably.
Cache class doesn’t care what type of object it works with. The only
Cacheable aspect of type matters.
On The Contrary
Like with an abstract class, objects that implement one interface should have some common behavior. So what happens if we define a
Cache interface instead of an abstract class?
Interfaces provide only methods signatures, they don’t have any logic. In the terms of types: they provide only one aspect of the object’s behavior.
That means that we can create different types that implement
Cache: for example
Log. It may look like flexibility but ends up with god objects with many different empty or never used methods.
An interface annotates an aspect of a type. When we define a new base type, there is no need to extract an interface from classes. Use abstract classes instead.