Object Fundamentals

Object-Oriented Programming (OOP) is based around the notion of objects. This paradigm of programming has gain high popularity in the past decade and certainly is still very valuable among developers. We are going to take a closer look at objects, classes, methods, inheritance, visibility and scope within classes. Once you have a good understanding of those concepts, it would be easier to envision OOP in the bigger picture.

First of all, we need to address confusion between classes and objects. When studied in college, it took me some time to understand which one is which and not to use them interchangeably.

You can think of a class as a sort of a template or a blueprint that is used to generate objects. A class is a declaration of how an object is supposed to look like. Incidentally, class also becomes a type of an object. You can have several objects on your hands, and those objects will be differentiated by a type they have. You can also have several objects of the same type too. Those will be different in their instances, i.e. having different values for the same property for example.

Objects, as already mentioned, are the result of that blueprint or recipe. Objects is data, structured according to the class definition. Objects of the same class (or type) share same structure: same properties, same methods, same constructors. Values may differ, but the structure will stay the same.

Speaking of which, properties are variables defined within the class. Properties can be variables of primitive types, or of other object types. For example, your object can hold string like title, integer like serial number, and also it can hold Author type object for the purposes of knowing who created this entity. One thing to note about properties is that one have to note the visibility of this particular variable. There are several keywords for that: public, private, and protected. Public visibility means that the variable can be accessed by any caller from the outside of the object as well as inside of the object. There is no restriction to access. Private visibility means that this variable can only be accessed from within this class, and from nowhere else. Protected visibility means that only this class and all classes that inherit this class can access this variable. These visibility determines the scope of the variable. Scope is context in which the variable is accessible.

At this stage it is pretty easy to assign variables to class. In fact, some languages even allow you to create new variables for class without declaring them within class at first. It is not a good practice though, since the client cannot completely rely on these variables as they are not guaranteed – they can be assigned or they might not even exist. What we want is to bring some order into the class structure. For example, we might want to make certain properties be required vs optional. Or we might want to ensure that a certain variable gets a particular type assigned to it, in case the language you are using is not strong-typed.

Best way to solve this problem is through different available methods. Methods allow objects to perform tasks. They are declared within the class, and within class only. Methods can have a return type, and can accept a certain number of parameters as an input. Methods, like properties, also can have visibility: public, private, or protected.

One of the most important methods that an object should have is constructor method. Constructor method is called upon object creation, and is therefore useful in setting the object’s defaults up. Constructor method is not required though. If you omit it, the object creation will still happen. In constructor we can pass values for properties to be set up, and therefore instantiate object with ready made set of values.

Beside constructors there can be as many methods in a class as you wish. It is a good practice to create methods to deal with properties, namely, accessors and mutators. What these methods do is access or modify properties of the class instead of direct access to properties. Why do we need that? Well, for one, creating a uniform access to variables removes a risk of misspelling and creating or requesting a new variable. We can be sure that through this method we always modify the same variable. And then, when accessing variables you might want to create pseudo-variables. Imagine we have an Employee object. It has properties such as firstName and lastName. Instead of accessing each one every time, for convenience sake, we can create getFullName() accessor, which will return two of those variables concatenated in one variable.

// Base Class in PHP
class Product
{
    private   $title;
    private   $producerLastName;
    private   $producerFirstName;
    protected $price;
    private   $discount = 0;

    public function __construct(
        string $title,
        string $firstName,
        string $lastName,
        float  $price
    ) {
        $this->title             =$title;
        $this->producerFirstName =$firstName;
        $this->producerLastName  =$lastName;
        $this->price             =$price;
    }

    public function getProducerFirstName()
    {
        return $this->producerFirstName;
    }
    public function getProducerLastName()
    {
        return $this->producerLastName;
    }
    public function setDiscount($num)
    {
        $this->discount = $num;
    }
    public function getDiscount()
    {
        return $this->discount;
    }
    public function getTitle()
    {
        return $this->title;
    }
    public function getPrice()
    {
        // Here we get the discounted price
        return ($this->price - $this->discount);
    }
    public function getProducer()
    {
        return $this->producerFirstName . ” ”
            . $this->producerLastName;
    }
    public function getSummaryLine()
    {
        $base  = "{$this->title} ( {$this->producerLastName}, ";
        $base .= "{$this->producerFirstName} )";

        return $base;
    }
}

Lastly, OOP wouldn’t be itself without the notion of inheritance. Inheritance is the means by which one or more classes can be derived from a parent or base class. The derived class is called a child or a subclass. Child classes inherit all properties and methods that were available in the parent class. Child class will also add new functionality or override parent functionality (if the parent method permits overrides). Inheritance helps separation of responsibilities into related classes. For example, what if you wanted to create a Person class. This class would represent accounts in all social media platforms. How many properties would it need to have? How many methods? It would be necessary to store all of the data and methods so that all of those platforms would work with it. Can you imagine trying to maintain this kind of code? That’s where inheritance matters. It allows us to create Person class that would have properties and methods that all of its children would guarantee needing and sharing. And when it comes to specifics, one will just need to extend the class and add those extra specific methods and properties, thus reducing complexity of classes.

// Child Class in PHP
class AudioTrackProduct extends Product
{
    private $playLength;
    public function __construct(
        string $title,
        string $firstName,
        string $mainName,
        float  $price,
        int    $playLength
    ) {
        parent::__construct(
            $title,
            $firstName,
            $mainName,
            $price
        );
        $this->playLength = $playLength;
    }
    public function getPlayLength()
    {
        return $this->playLength;
    }
    // Overriding parent method
    public function getSummaryLine()
    {
        $base  = "{$this->title} ( {$this->producerLastName}, ";
        $base .= "{$this->producerFirstName} )";
        $base .= ": playing time - {$this->playLength}";
        return $base;
    }
}
// Child Class in PHP
class BookProduct extends Product
{
    private $numPages;
    public function __construct(
        string $title,
        string $firstName,
        string $mainName,
        float  $price,
        int    $numPages
    ) {
        parent::__construct(
            $title,
            $firstName,
            $mainName,
            $price
        );
        $this->numPages = $numPages;
    }
    public function getNumberOfPages()
    {
        return $this->numPages;
    }
    // Overriding parent method
    public function getSummaryLine()
    {
        $base  = parent::getSummaryLine();
        $base .= ": page count - $this->numPages";
        return $base;
    }
    // Overriding parent accessor
    public function getPrice()
    {
        return $this->price;
    }
}

When creating an object we must keep in mind that if we extend it from a parent class and we add new features to constructor, we must properly handle it: call and handle parent constructor, and then handle whatever current class properties you are trying to address.

There is definitely more to Object-Oriented Programming. This is just the beginning. But even here you can see how OOP is designed to reduce complexity and bring structure to data.

Leave a comment