3.2 · Object-oriented programming (classes, inheritance, interfaces)

Level 3 · Databases & OOP

3.2Object-oriented programming (classes, inheritance, interfaces)

Goal: think and program in objects (classes, properties, methods, $this) and master OOP (encapsulation, inheritance, polymorphism, interfaces, traits) — the paradigm of modern PHP and frameworks.
Estimated time: 13 min · self-paced reading · If you only have 5 min: read “The essentials in 30s” + the diagram.

The essentials in 30 seconds

  • The class is a blueprint, the object an instance: properties (data) + methods (behaviours), new to create, $this for the current object, __construct to initialize.
  • Encapsulation protects state: private properties + validating getters/setters — the object guarantees its own consistency.
  • Inheritance, interfaces and traits structure: extends to specialize, interface to contract, trait to share without inheritance.

Running case — Riad tidies his spaghetti code into objects

Riad, web developer in Constantine, manages users and orders with arrays and scattered functions: an invalid email slipped in anywhere breaks sending. He models a Utilisateur class (private properties, validating setters, initializing constructor), an Admin class that extends Utilisateur, and a Notifiable interface both implement. Invalid data is rejected at the source, the code reads like the business.

This same case returns in the lesson, the diagram, the script and the 48h challenge.

1. Classes, objects and encapsulation

OOP organises code around objects grouping data and behaviours. The class is the blueprint: properties (a user has a name, an email) and methods (they can log in). You create objects with $user = new User(), the __construct() constructor initializes at creation, and $this refers to the current object ($this->nom).

Encapsulation controls access via visibility: public (everywhere), private (class only), protected (class + descendants). Properties are made private and accessed through validating getters/setters: no invalid email can be set directly. The object protects its state — a key robustness principle Riad applies to every entity.

2. Inheritance, polymorphism, interfaces and traits

Inheritance (class Admin extends User) reuses and specializes: Admin gets everything from User, adds or overrides methods. Polymorphism lets different classes answer the same method each in its own way — ideal for generic code. Abstraction hides complexity behind simple interfaces.

Interfaces are contracts: they declare methods a class MUST implement, without saying how — you program “to a contract”, you decouple (essential for testing). Traits share methods between classes without inheritance (PHP allows only one extends). Riad remembers the hierarchy: contract first (interface), sharing next (trait), specialization last (extends).

Common misinterpretation: “OOP is just classes with functions inside, and private is useless.” No. Without encapsulation (all public), state gets corrupted from everywhere with no control; without interfaces, code couples to concrete implementations and becomes untestable. OOP is a discipline of protection and contracts, not mere tidying.
The four pillars + two tools From protected object to decoupled code Class → objectProperties + methods, new, $this+Encapsulationprivate + validating getters/setters+Inheritance + polymorphismextends, overriding, same method Interfaces = contracts to implement; traits = shared methods without inheritance.
From protected object to decoupled code
Text version of the diagram (SEO / screen readers / translation): 1) Class and object: Riad writes the Utilisateur blueprint then instantiates each client with new. 2) Encapsulation: private properties only change via setters validating the email. 3) Inheritance and polymorphism: Admin extends Utilisateur and overrides its rights; each role answers peutAcceder() in its own way. 4) Contracts and sharing: the Notifiable interface and a logging trait decouple the code. Lesson: protect, specialize, contract.

The $this that mistook itself for others

“My Admin class was changing clients' balances: it had everything public.”
Encapsulation learned the next morning, over strong coffee

Private first: an object keeps its business to itself.

🔎 Concrete example — Encapsulated class and inheritance

Riad models a user validating its email, then an admin.

nom = $nom;
    $this->setEmail($email);
  }
  public function setEmail(string $email): void {
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
      throw new InvalidArgumentException('Invalid email.');
    }
    $this->email = $email;
  }
  public function getEmail(): string { return $this->email; }
}
class Admin extends Utilisateur {
  public function peutAcceder(string $ressource): bool { return true; }
}

Reading: initializing constructor, private-backed validating setter, specializing inheritance.

Lesson: an invalid email is rejected at the source — the object guarantees its consistency.

Section vocabulary

OOP / class / object
Paradigm organising code into objects (data + behaviours); the class is the blueprint, the object an instance (new); $this = current, __construct = initialization.

Simple example: new Utilisateur('Riad', 'riad@fictitious-example.test').

What it is not: scattered functions and variables with no blueprint.

Reflex: model each business entity as a class.

Encapsulation / visibility
Grouping and controlling access: public (everywhere), private (class only), protected (class + descendants); private + getters/setters to protect state.

Simple example: Riad's setEmail refusing the invalid.

What it is not: public properties modifiable any which way.

Reflex: private properties by default.

Inheritance
class Admin extends User: reuses the parent's members, adds or overrides; an “is a kind of” relationship.

Simple example: Admin inherits from Utilisateur and overrides peutAcceder().

What it is not: copy-pasted methods between classes.

Reflex: inherit to specialize, not to copy.

Polymorphism / abstraction
Same method, different behaviours per class; hiding complexity behind simple interfaces.

Simple example: Each role answers peutAcceder() in its own way.

What it is not: a giant switch on the object type.

Reflex: call the method, let the object decide.

Interfaces / traits
Interface: contract of methods to implement (decouple, test). Trait: horizontal sharing of methods without inheritance.

Simple example: Notifiable implemented by Utilisateur and Order.

What it is not: depending everywhere on a concrete class.

Reflex: depend on interfaces, share via traits.

In practice — Thinking and programming in objects

  1. Create a class (e.g. User) with properties (name, email) and methods; instantiate with `new`, initialize via __construct, use $this.
  2. Apply ENCAPSULATION: private properties, access via validating getters/setters; type the properties.
  3. Create a class that INHERITS (extends) and OVERRIDES a method; observe reuse and specialization.
  4. Define an INTERFACE (contract) and a class implementing it; explore a trait to share methods.
You think and program in objects (classes, properties, methods, $this) and master OOP (encapsulation, inheritance, polymorphism, interfaces, traits) — the paradigm of modern PHP and frameworks.

Ready-to-say script — presenting your object modelling (30 s)

“Users are modelled as a class: private properties, initializing constructor, setters validating the email. Admin inherits from Utilisateur and overrides its rights, and both implement the Notifiable interface. Invalid data is rejected at the source.”

Say in review; show the setter throwing the exception.

Copy-paste template — encapsulated class + interface

nom = $nom;
    $this->setEmail($email);
  }
  public function setEmail(string $email): void {
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
      throw new InvalidArgumentException('Invalid email.');
    }
    $this->email = $email;
  }
  public function getEmail(): string { return $this->email; }
}
class Admin extends Utilisateur {
  public function peutAcceder(string $ressource): bool { return true; }
}

Independent

One encapsulated Client class is enough to make generated quotes reliable.

SME in Constantine

Riad models linked clients, orders and admins, each validating its state.

Product team

Enforce interfaces and encapsulation for testable modules across teams.

Beginner

This week: one class with two private properties and one validating setter.

✓ Best practices

  • Private properties by default, access via validating methods.
  • Type properties and signatures (robustness + readability).
  • Program to a contract (interfaces) to decouple and test.

✗ Common pitfalls

  • Putting everything public (state corruptible from everywhere).
  • Inheriting to copy code instead of specializing an “is a”.
  • Confusing interface (contract) with inheritance (reuse).

Key takeaways

  • OOP organises code into OBJECTS (data + behaviours). CLASS = blueprint; OBJECT = instance (new). $this = current; __construct = initialization.
  • ENCAPSULATION: VISIBILITY (public/private/protected); private + validating getters/setters to protect state. INHERITANCE (extends): reuse and specialize.
  • POLYMORPHISM (same method, different implementations) and ABSTRACTION. INTERFACES = contracts (decouple, test); TRAITS = sharing without inheritance.
  • OOP is the CAPE of modern PHP and FRAMEWORKS: organise, reuse, maintain — a change of thinking that takes practice.

48h challenge — apply tomorrow

Write 1 encapsulated class (private + validating setter) and 1 child class overriding 1 method.

Section exit checklist
  • I tell class (blueprint) apart from object (instance).
  • My properties are private with validation.
  • I inherit to specialize and contract via interface.
Self-rating 1-5: can invalid state exist in my objects?do my dependencies target interfaces?

Frequently asked questions

Why switch to OOP when procedural works?

Procedural scatters data and functions with no structure: on a growing app, you no longer know which functions go with which data. OOP groups (object = data + behaviours), models the business (User, Order), protects state (encapsulation) and reuses (inheritance, traits) while decoupling (interfaces). It is the paradigm of level-4 frameworks — the cape to earn.

Encapsulation, inheritance, interfaces: how to grasp them concretely?

Encapsulation = protect and group: an account balance only changes via deposit/withdraw that check (never direct assignment). Inheritance = “is a kind of”: Dog extends Animal reuses and specializes (bark). Interface = contract: the class commits to providing methods, the rest of the code depends on the contract (testable). Trait = horizontal sharing when a single extends is not enough.

Check your understanding

Why private properties + getters/setters?

Additional resources (optional, to go further)

Level 3 examFresh, harder questions to test what you've learned