I think it's important to, first, clarify terminology, in order to more elaborately answer this question.
- inheritance
- Inheritance is actually broadly applied to a lot of Object-Oriented programming principles and concepts. It just entails one thing bred from another. So whether you are implementing an interface or extending a class you are still using a form of inheritance. They aren't mutually exclusive concepts.
- interface
- Try to think of an interface like you would a contract. The contract itself is just a document, usually between two or more parties, that lays out the rules of their relationship. Interfaces, specifically in the context of OOP and PHP, do not provide implementation. They only provide the required public methods that an implementing class MUST implement. Interfaces also cannot be instantiated on their own.
- abstract class
- The abstract class is similar to an interface in that it cannot be instantiated on its own, but does not necessarily enforce a contract on the extending class. Since it's an actual class, and not just an interface, it also allows for implementation. This implementation can be supplied by the abstract class itself, or left up to the extending class, if the method is declared as
abstractin the abstract class. It also allows for the implementation of properties and private/protected methods, because the inheritance here acts like a base class and not just a requirement.
- The abstract class is similar to an interface in that it cannot be instantiated on its own, but does not necessarily enforce a contract on the extending class. Since it's an actual class, and not just an interface, it also allows for implementation. This implementation can be supplied by the abstract class itself, or left up to the extending class, if the method is declared as
So to answer the question, "why do we have abstract classes in PHP", because it's useful. You may see these as intractable ideas at first, but they actually can work together to provide conjoined utility.
Example
Consider that some times an interface isn't enough to create a useful implementation. The interface can only enforce that a method exists and that its signature is compatible with the implemented interface. There may be cases when you wish to provide default implementations of an interface, for example.
interface Device {
public function input(Stream $in);
public function output(): Stream;
}
abstract class DefaultDevice implements Device {
protected $buffer = "";
public function input(Stream $in) {
$this->buffer .= $in->read(1024);
$this->process();
}
abstract protected function process();
}
So now any class that extends DefaultDevice can either choose to override the implementation of the input method or not. It also has to implement a process method even though the interface does not require it. This means other classes implementing the Device interface can be backwards compatible and this remains an implementation detail.
Further Example
Separating implementation from specification is generally a key attribute of well-written software.
Take a look at the Device interface itself, as a good example. We rely on the input method to accept a Stream type and the output method to return a Stream type. Since Stream, itself, can actually be an interface this means that any type implementing Stream is acceptable. So I could create my own class and implement the Stream interface without ever breaking this code.
class CustomStream implements Stream {
public function read($bytes = 1024) {
/* implementation */
}
public function write($data) {
/* implementation */
}
}
$device->input(new CustomStream); // this will not throw an error
Answer from Sherif on Stack OverflowPHP Abstract Classes, PHP Interfaces
abstraction - Why are abstract classes necessary in PHP? - Stack Overflow
php - Is it good practice to declare and set properties in abstract classes? - Software Engineering Stack Exchange
Creating abstract properties in PHP - PHP - SitePoint Forums | Web Development & Design Community
Videos
I read about it online and still can't understand what these two is about. How does it work and when do you use these two? Can someone give example and explain these to me in simple words? Thanks!
I think it's important to, first, clarify terminology, in order to more elaborately answer this question.
- inheritance
- Inheritance is actually broadly applied to a lot of Object-Oriented programming principles and concepts. It just entails one thing bred from another. So whether you are implementing an interface or extending a class you are still using a form of inheritance. They aren't mutually exclusive concepts.
- interface
- Try to think of an interface like you would a contract. The contract itself is just a document, usually between two or more parties, that lays out the rules of their relationship. Interfaces, specifically in the context of OOP and PHP, do not provide implementation. They only provide the required public methods that an implementing class MUST implement. Interfaces also cannot be instantiated on their own.
- abstract class
- The abstract class is similar to an interface in that it cannot be instantiated on its own, but does not necessarily enforce a contract on the extending class. Since it's an actual class, and not just an interface, it also allows for implementation. This implementation can be supplied by the abstract class itself, or left up to the extending class, if the method is declared as
abstractin the abstract class. It also allows for the implementation of properties and private/protected methods, because the inheritance here acts like a base class and not just a requirement.
- The abstract class is similar to an interface in that it cannot be instantiated on its own, but does not necessarily enforce a contract on the extending class. Since it's an actual class, and not just an interface, it also allows for implementation. This implementation can be supplied by the abstract class itself, or left up to the extending class, if the method is declared as
So to answer the question, "why do we have abstract classes in PHP", because it's useful. You may see these as intractable ideas at first, but they actually can work together to provide conjoined utility.
Example
Consider that some times an interface isn't enough to create a useful implementation. The interface can only enforce that a method exists and that its signature is compatible with the implemented interface. There may be cases when you wish to provide default implementations of an interface, for example.
interface Device {
public function input(Stream $in);
public function output(): Stream;
}
abstract class DefaultDevice implements Device {
protected $buffer = "";
public function input(Stream $in) {
$this->buffer .= $in->read(1024);
$this->process();
}
abstract protected function process();
}
So now any class that extends DefaultDevice can either choose to override the implementation of the input method or not. It also has to implement a process method even though the interface does not require it. This means other classes implementing the Device interface can be backwards compatible and this remains an implementation detail.
Further Example
Separating implementation from specification is generally a key attribute of well-written software.
Take a look at the Device interface itself, as a good example. We rely on the input method to accept a Stream type and the output method to return a Stream type. Since Stream, itself, can actually be an interface this means that any type implementing Stream is acceptable. So I could create my own class and implement the Stream interface without ever breaking this code.
class CustomStream implements Stream {
public function read($bytes = 1024) {
/* implementation */
}
public function write($data) {
/* implementation */
}
}
$device->input(new CustomStream); // this will not throw an error
an abstract class is used to provide a set of data members or methods to be made available to classes which inherit from it, even though the base class is not particularly useful (and should never be instantiated on its own) without an inherited implementation.
from here, inheritance takes over.
an interface on the other hand is to provide a set of rules for implementation that require each class that uses the interface to implement the specifications found therein. classes implementing the same interface do not need to inherit from each other, they implement the interface so they can be used in any application requiring that set of functionality.
This may be a personal preference, but I avoid having base classes for the sake of sharing properties. Particularly in data classes. I don't mind the repetition, and I avoid locking my classes into a fixed "data" hierarchy.
There are enough problems with inheritance, particularly over time as the code base grows, that I am reluctant to share methods through a class hierarchy, and even more reluctant to share properties through a class hierarchy.
...
Hm. I just noticed that you mentioned "static" properties. Rather than static (i.e. global) properties in a base class, you're better off with a separate, single instance of something dispensed by a factory. Make sure you provide for concurrency to avoid race conditions.
To answer your question, yes. If the abstract class is the logical place for the property then put it there. Use the tools that classes and OOP gives you.
"overtime the original structure/layout of these abstract properties is forgotten and could be left at there default static values or even forgotten(not used) completely."
This implies to me that developers using/creating the abstract class or child classes are required to do something with these properties. If that is true, try to come up with a class design that forces a developer to deal with this. That's better then to trust everyone to always do it correctly.
You mention changing static values. Static properties are shared between all class instances, so by changing their value in one object you change it for all. Multiple objects changing global state is something you want to avoid, because it is difficult to keep all changes in the correct order.