Since writing this article, I have rewritten it in much more detail.
If you have any experience with Object Orientated Programming (OOP), you’ll of probably heard of APIE. If you haven’t, then quite simply APIE is an acronym for the 4 most important concepts of OOP.
APIE stands for Abstraction, Polymorphism, Inheritance and Encapsulation. Each of these are huge subjects in their own right and together form what is know as OOP. Below I aim to explain the basis to each of these concepts, focusing on what they mean, when they should and shouldn’t be used and how you should go about writing code, with them in mind.
Note: I am going to explain these in the EIAP order rather than APIE, because it just makes more sense.
Encapsulation
One of the main benefits to using OOP over procedural programming is how easy it is to keep your codebase tidy and therefore more maintainable and with less code smells. Encapsulation is the driving factor behind this by means of creating classes for each entity and responsibility within a system. These classes are used to store and manage everything for the entity in question. A classic example is a user class which could store a users forename, surname and email and contain a methods to retrieve this data. The benefit of this is that when you want to perform an action on a user, e.g. modifying their name or email address or deleting them. Everything is done from one place.
class User { private $user_id; private $forename; private $surname; private $email; public function getId() { return $this->user_id; } public function setId($id) { $this->user_id = (int) $id; } public function getForename() { return $this->forename; } public function setForename($forename) { $this->forename = $forename; } public function getSurname() { return $this->surname; } public function setSurname($surname) { $this->surname = $surname; } public function setFullName() { return $this->forename . ' ' . $this->surname; } public function getEmail() { return $this->email; } public function setEmail($forename) { $this->email = $email; } public function delete() { // delete user from data storage } }
Inheritance
Whether you are writing procedural code or OO, one thing you never want to do, is disobey the Don’t Repeat Yourself (DRY) principle, by copy and pasting code all over the shop. Thankfully with inheritance in OOP this isn’t necessary. Instead if you have multiple entities that are going to require the same functionality, you can build a parent class which contains the core functionality, that each of the similar classes require and then leave the differences to the child classes to implement. As an example lets create 3 classes: Pet, Cat and Dog, the parent class (Pet) will contain methods to set a name for the pet, as both cats and dogs have names. Then in the Cat and Dog Classes and individually set the noise the pet makes, because this will be different.
class Pet { private $name; public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } } class Cat extends Pet { private $noise = 'Meow'; } class Dog extends Pet { private $noise = 'Woof'; } $dog = new Dog(); $dog->setName('Buster'); echo $dog->getName() . ' says hello'; // Buster says hello
Abstraction
Abstraction is sort of like inheritance, but with a little addition. When defining an abstract class, you are able to define attributes and methods that child classes will have access too, just like a standard parent class. The little addition is that inside the abstract class, you are able to define a set of rules as such, by defining which methods must be implemented by any child class of the abstract class. Using abstraction ensure that all child classes being built, have all of the methods they require to work correctly. This hopefully means less bug.
abstract class Document { public $fileName; abstract public function render(); public function getFilename() { return $this->fileName; } public function setFilename($fileName) { $this->fileName = $fileName; } } class PDFDocument extends Document { public function render() { //render a PDF Document } } class XLSDocument extends Document { public function render() { //render an XLS Document } } $xls = new XLSDocument(); $xls->setFilename('Weekly Sales'); $xls->render();
Polymorphism
Polymorphism is the hardest of the 4 characteristics to grasp and remember. If typically means “many form”, at least this is how I originally remember it. As you get more advanced with OOP, you will realise what an amazing and essential thing polymorphism is. Without it unit testing would become nearly impossible. What polymorphism essentially allows you to do, is perform the correct action without knowing what’s going on behind the scenes. I won’t repeat the above example, but it’s an excellent demonstration, both the PDFDocument and XLSDocument classes have render methods. This means regardless of how your object was created and which class the object is actually an instance of (PDFDocument or XLSDocument), you can always call the render method and the correct functionality will be executed. You might be thinking, “how often will I not know what class I have an instance of?” well you will be surprised, if you use the factory pattern, the answer would be “a lot”.
I hope that sheds some light on the fundamentals of OOP. If you have any questions, please leave a comment.
14 Love This
Excellent way of describing, and fastidious piece of writing
Howdy! Would you mind if I share your blog with my twitter group?
There’s a lot of folks that I think would really enjoy your
content. Please let me know. Thank you
Of course not 😀 In fact it would be much appreciated. Thank you.
Needed to compose you a very little word to thank you yet again regarding the nice suggestions you’ve contributed here.
Thank you, I actually wrote a successor to this blog here: https://www.jakowicz.com/apie-revisited/
I think you find it interesting. Thanks.