In the world of programming, the most standard codes are those that have the least code duplication. But there are times when we have to write the same code repeatedly to do almost the same thing with small changes. In this situation, we must look for solutions that minimize these repetitions. To combat these repetitions, we use abstract classes and methods.
Consider the production line of a donut factory. Donuts are cooked in the same way. After that, a suitable coating sauce with different colors and flavors such as colored cream, chocolate, colored tablets, and. It is poured on them. Depending on the type of sauce that is poured on them, they are packed. You can see that all donuts, regardless of their taste or shape, have the same cooking method. The wrong way is to create a separate production line for each donut color. Does this make sense? Another method is to have the production line shared until the cooking stage. The donuts are then sorted separately at the end of the sauce pouring stage and packed at the end. The following code shows the separate chocolate donut production line in the ChocolateDonut class:
class ChocolateDonut {
public function make () {
return $ this
-> makeDough ()
-> moldDonut ()
-> fryDonut ()
-> addChocolate ()
-> packChocolateDonut ();
}
protected function makeDough () {
print "make donut dough, first." ;
return $ this ;
}
protected function moldDonut () {
print "then, mold donut to have a wheel shape." ;
return $ this ;
}
protected function fryDonut () {
print "fry the donut carefully." ;
return $ this ;
}
protected function addChocolate () {
print "Add enough chocolate on the donut!" ;
return $ this ;
}
protected function packChocolateDonut () {
print "Pack donut with brown Packing!" ;
return $ this ;
}
}
$ chocolateDonut = new ChocolateDonut ();
$ chocolateDonut -> make ();
The same steps are repeated to prepare donuts with strawberry sauce:
class StrawberryDonut {
public function make () {
return $ this
-> makeDough ()
-> moldDonut ()
-> fryDonut ()
-> addStrawberrySauce ()
-> packStrawberryDonut ();
}
protected function makeDough () {
print "make donut dough, first." ;
return $ this ;
}
protected function moldDonut () {
print "then, mold donut to have a wheel shape." ;
return $ this ;
}
protected function fryDonut () {
print "fry the donut carefully." ;
return $ this ;
}
protected function addStrawberrySauce () {
print "Add enough strawberry on the donut!" ;
return $ this ;
}
protected function packStrawberryDonut () {
print "Pack donut with pink Packing!" ;
return $ this ;
}
}
$ strawberryDonut = new StrawberryDonut ();
$ strawberryDonut -> make ();
But we said that there is no need to repeat the donut preparation codes. Because the process of preparing donuts, except for the decoration part, is conventional and repetitive. So we turn duplicate pieces of code into a contract using the abstract:
abstract class DonutTemplate {
public function make () {
return $ this
-> makeDough ()
-> moldDonut ()
-> fryDonut ()
-> addDressing ()
-> packDonut ();
}
protected function makeDough () {
print "make donut dough, first." ;
return $ this ;
}
protected function moldDonut () {
print "then, mold donut to have a wheel shape." ;
return $ this ;
}
protected function fryDonut () {
print "fry the donut carefully." ;
return $ this ;
}
protected abstract function addDressing () ;
protected abstract function packDonut () ;
}
class ChocolateDonut extends DonutTemplate {
protected function addDressing ()
{
print "Add enough chocolate on the donut!" ;
return $ this ;
}
protected function packDonut ()
{
print "Pack donut with brown Packing!" ;
return $ this ;
}
}
class StrawberryDonut extends DonutTemplate {
protected function addDressing ()
{
print "Add enough strawberry sauce on the donut!" ;
return $ this ;
}
protected function packDonut ()
{
print "Pack donut with pink Packing!" ;
return $ this ;
}
}
$ chocoDonut = new ChocolateDonut ();
$ chocoDonut -> make ();
As you can see in the code, an abstract class is a class that contains at least one abstract method. Abstract methods have no implementation and only force child classes to implement those methods. In the above code, using the keyword extends, we have forced the child class to follow the abstract parent class. If the ChocolateDonut class does not implement the addressing method, the program will encounter an error.
Making new donuts with any decorative sauce is enough to implement a new donut class, an abstract class called DonutTemplate.
Conclusion
In this article, we examined the abstract and how to use it. As you can see, using this method reduces the lines of code and makes it legal and reliable. In teamwork, creating contracts helps the team leader receive integrated codes. One of the main uses of the abstract is when you want to force your team of developers to create several methods, and you prefer their methods to conform to the structures defined by you. Another important point is that a class can implement multiple interfaces but inherit only from one abstract class. Because the interface is just a set of abstract methods, to learn more about the interface, you can read our article about the interface and its application.