Lab 01: Traits, Abstract Classes & Interfaces

Objective

Master PHP's code-reuse mechanisms: traits for horizontal code sharing, abstract classes for enforced template patterns, and interface contracts for polymorphic type systems. Build a product discount system that demonstrates all three working together.

Background

PHP uses single inheritance — a class can only extend one parent. Traits solve this limitation by providing "mixins" — reusable method bundles that are copy-pasted into a class at compile time. Abstract classes enforce a template method pattern: they define the algorithm skeleton but leave specific steps to subclasses. Interfaces define contracts: any class implementing an interface must provide all listed methods, enabling duck-typed polymorphism without inheritance.

Time

30 minutes

Prerequisites

  • PHP Foundations Lab 07 (OOP), Lab 08 (Inheritance)

Tools

  • Docker: zchencow/innozverse-php:latest


Lab Instructions

Step 1: Traits for horizontal reuse

A trait is a group of methods intended for reuse. Unlike a parent class, you can use multiple traits in one class. The methods are literally copied into the class body — there is no runtime dispatch overhead. Traits can have properties too, but they must be compatible with any property declared in the using class.

💡 Traits are compile-time copy-paste, not runtime dispatch. When PHP encounters use Timestampable, it copies all trait methods directly into the class definition. This means there is zero performance overhead — calling $p->setCreatedAt() is identical to calling a method defined directly in Product. The PHP manual says: "Traits are a mechanism for code reuse in single inheritance languages."

📸 Verified Output:


Step 2: Trait conflict resolution

When two traits define the same method name, PHP throws a fatal error — you must resolve the conflict explicitly using insteadof and as.

📸 Verified Output:


Step 3: Abstract classes — Template Method pattern

An abstract class cannot be instantiated directly. It defines an algorithm skeleton with abstract methods that must be implemented by concrete subclasses. This is the Template Method design pattern — the parent defines the steps, subclasses fill in the details.

📸 Verified Output:


Step 4: Interfaces — polymorphic contracts

An interface is a pure contract: no method bodies, no properties (except constants). Any class implementing the interface guarantees it has those methods. This enables dependency injection — you type-hint on the interface, and any implementation works.

📸 Verified Output:


Summary

Mechanism
Key Rule
Best For

trait

use multiple traits in one class

Shared behaviour across unrelated classes

abstract class

Can't instantiate; defines template

Algorithm skeleton with variation points

interface

Pure contract; implement multiple

Decoupled type system, dependency injection

insteadof

Trait conflict resolution

Multiple traits with same method name

Priceable&Taxable

Intersection type hint

Require multiple interfaces simultaneously

Further Reading

Last updated