As developers, we have encountered scenarios where some of the code we write can be reused by other code pieces. This has brought the concepts of code reuse in paradigms like object oriented programming. In this article, the author seeks to explain when to reuse code as well as how to achieve code reuse.
Reusing code from one class in another class tells, those classes have certain methods and properties that are common to each other. In this case reusing them will help to prevent code duplication. There are two ways a class can relate to another class and we will use the diagram below to aid our understanding between these two relationships.
From the diagram above, we have a house, BathHouse
which is a type of house and BathTub
which is contained in a BathHouse
. Considering these as separated classes, we can identify some relationships between them. A BathHouse
is a specific type of a house which means BathHouse
IS-A House, while BathHouse
has a BathTub
which is BathHouse
Has-A BathTub
. Using these concepts will help us understand when to implement various relationships in our codes. From here, we are going to take each relationship type, explain them a bit further and implement them with concrete examples.
One way that a class can relate to the other is when the one is a type of the other. For instance when we take a car we can say it is a type of a vehicle. A teacher is also a type of staff. When one class is a type of the other, we say they have “IS-A” relationship.
Inheritance is a design patter to implement a “IS-A” relationship between classes. Here, there is a parent-child relationship where a parent class with its own methods and properties and later a child class is created that can use the code from the parent class.
To achieve inheritance, we use the keyword extends
. Let’s see it in practice:
// The parent’s class code
class House {
protected $name;
protected $size;
}
// The child can use the parent's class code
class BathHouse extends House { }
From the above code, House then become a parent class and the BathHouse which extends to the parent class is a child class.
Another important means to relate classes is when a class is part of another class. For instance, when we take a car class, it can be composed of an engine class as well as other components to achieve a holistic functioning car class.
Composition is a design patter to implement a “HAS-A” relationship between classes. Here, an instance variable is used to refer to other classes in its composed classed.
To achieve composition, one class is composed in other class as instance field. Let’s see it in practice:
class BathTub { }
class BathHouse {
BathHTub tub;
}
We are going simulate using an MVC pattern to build a sample project. Here we will see how we can make use of these two concepts. With MVC app, when user requests to view a page by entering a URL. The Controller receives that request, uses the Models to retrieve all of the necessary data and organizes it, which then pass the data to the view to present the webpage to the user.
Usually the application has multiple controllers and to prevent multiple code duplicates, it is better to create a base controller from which other controllers can use to achieve various tasks. In this case, we can infer some relationship between the base controller and the controllers we will be creating. The controllers to be created will be of a type of the base controller so the inheritance can be used here, not composition.
class BaseController {
public function loadView($view, $data=[]){
if(file_exists($view .'.php')){
require_once($view .'.php');
} else {
require_once('404.php');
}
}
public function loadModel($model){
require_once($model . '.php');
return new $model(new Database());
}
}
Here, we have two methods that our BaseController
class performs; loading view and model. But in the loadModel
method, we are passing a an instance of database class to the model so it can use it to perform the necessary operations on our our database.
Models are know to be a representation of real world object. Here, we a model an aspect of our database as a blog post, though a Blog
database might have a lot of representations like users, etc. But we just need the Blog Posts, which we can say that our database has a blog post
<?php
class Blog {
private Database $blogpost;
public function __construct(Database $blogpost) {
$this->blogpost = $blogpost
}
// Get All BlogPost
public function getBlogs() {
$this->blogpost->query("SELECT * FROM blog");
return $this->blogpost->resultset();
}
// Get BlogPost By Id
public function getPostById($id) {
$this->blogpost->query("SELECT * FROM posts WHERE id = :id");
$this->blogpost->bind(':id', $id);
return $this->blogpost->single();
}
}
Now that we have a base controller which can help us work with views and models as well as having a model to interact with our database, we are going to create a specific controller to help us read all blog posts.
class BlogsController extends BaseController {
public function __construct() {
// Load Models
$this->blogModel = $this->loadModel('Blog');
}
// Load All Posts
public function index() {
$data = [
'posts' => $this->blogModel->getBlogs()
];
$this->loadView('blogs', $data);
}
}
Here, we have created a controller the get all blog posts from our model and send that to the view. We can now present our view to the user.
<?php foreach($data['posts'] as $post): ?>
<div class="card">
<div><h2> ?php echo $post->title; ?> </h2></div>
<hr/>
<div><p> ?php echo $post->body; ?> </p></div>
<?php endforeach;?>
So the view just loop through the array data structure and render the content as cards to the user.
Now that we have clearer view of these two class relationship concepts, we can now compare both and find out where one outshines the other. Though both have their pros and cons but that isn’t the main concern of this article. Hence, we have to understand the best cases where we either implement class relationships with composition and inheritance. Use composition between two classes if one cannot exit without another. From our examples above, the Model
class cannot exist without a Database
class. If a class just want to make use of another class’ functionalities and properties then inheritance will be helpful. With our controllers, it obvious that BlogsController
can exist completely without BaseController
.
I hope you found this piece useful having being briefed some background on the meaning of inheritance and composition, also established how classes can be related using inheritance and composition.