Objects

The term object orientation was coined by Alan Kay towards the end of the 1960s. He wrote about it himself:

I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages (so messaging came at the very beginning -- it took a while to see how to do messaging in a programming language efficiently enough to be useful).

Alan Kay

So objects are not just an add-on to procedural programming, they communicate with each other using messages. No wonder object orientation and event-driven architectures go so well together - they are very closely related.

Classes and objects

A class is the blueprint for an object, so to speak:

<?php declare(strict_types=1);

class Counter
{
    private int $counter = 0;

    public function increment(): void
    {
        $this->counter += 1;
    }
}
class.php

Here we have an object that represents a counter. An object encapsulates data (the counter value, initially 0) as well as code or the algorithms that operate on this data. This idea is in relatively stark contrast to the fact that source code is normally managed in a version control system, but the data of an application is stored in a database or similar persistence mechanisms, i.e. separately from each other.

We call the code methods, even if it says function in PHP. We can think of a method as a function that exists within an object.

Objects can also contain data, in our example the counter value, which is an int. We call this data attributes or properties of the object. To access the state of an object, i.e. the current attribute values, we use the special variable $this. To call a method, we use the arrow ->, which is also called the object operator in PHP. In other programming languages, . is used instead of the arrow.

$this

$this is a reserved variable name. If you try to reassign the variable $this, the program will terminate immediately:

<?php declare(strict_types=1);

class Counter
{
    public function increment(): void
    {
        $this = new Counter;
    }
}
reassignThis-will-fail.php
PHP Fatal error:  Cannot re-assign $this in reassignThis-will-fail.php on line 7
Output of reassignThis-will-fail.php

As we have just seen in this example, we use new to create an object from a class. This returns a reference to the created object instance, which we can use to send messages to the object:

<?php declare(strict_types=1);

class Counter
{
    private int $counter = 0;

    public function increment(): void
    {
        $this->counter += 1;
    }
}

$counter = new Counter;
$counter->increment();

var_dump($counter);
instance.php
instance.php:16:
class Counter#1 (1) {
  private int $counter =>
  int(1)
}
Output of instance.php

Instead of "send message", many people would say that we are calling a method. This sounds more like calling a function. Here again we see the tension between the idea of messaging ("OOP as it was meant to be") and a more classical understanding of programming (function calls) that is rooted in procedural programming.

We can create multiple counters that are independent of each other. In particular, each counter object has its own state:

<?php declare(strict_types=1);

class Counter
{
    private int $counter = 0;

    public function increment(): void
    {
        $this->counter += 1;
    }
}

$counter1 = new Counter;
$counter1->increment();
$counter1->increment();

$counter2 = new Counter;
$counter2->increment();

var_dump($counter1, $counter2);
counters.php
counters.php:20:
class Counter#1 (1) {
  private int $counter =>
  int(2)
}
counters.php:20:
class Counter#2 (1) {
  private int $counter =>
  int(1)
}
Output of counters.php

var_dump() shows us for each object after the class name (the #1 or #2) the number of objects created in this program run. In addition, the status of the object is displayed in the form of the current attribute values.

var_dump() is a good debugger that is always available.

Moving on

Visibility, i.e. the private and the public in the examples above, is a separate matter that needs more explanation.

To put an object into a workable state, we need a constructor.

If we now diligently define classes and then also bring third-party code into our application, naming conflicts are very likely to arise, especially for such simple and frequently used class names as Node, String, or Item. To avoid such naming conflicts, there are namespaces in PHP.

Questions for learning control

  1. Explain the difference between a class and an object.
  2. What advantages do objects have over procedural programming?
  3. What does garbage collection do?