Codementor Events

Class, Instance, Object, Interface, Trait, Types

Published Jul 11, 2024
Class, Instance, Object, Interface, Trait, Types

"We read to know we're not alone." ~ William Nicholson, Shadowlands

TL;DR:

  • Class: A blueprint defining properties and methods.
  • Object: A concretization of a class, often created with the new keyword.
  • Instances: Specific realizations of a class, often used interchangeably with objects.
  • Interface: Defines a contract that classes must implement, ensuring certain methods exist.
  • Abstract Class: A template for other classes, allowing shared functionality and mandatory methods.
  • Trait: Reusable code chunks that can be included in multiple classes.
  • Types (TypeScript): Ensure objects have a specific structure or methods, enhancing flexibility and reliability.

What is the difference between a:

  • Class
  • Instance
  • Object
  • Interface
  • Trait
  • Types (Bonus for TypeScript)

If you ask someone this question, you'll get a range of responses, from knowing none, some, or all of these concepts. It's essential to have a common understanding because these are core concepts of Object-Oriented Programming (OOP), which are fundamental in languages like PHP, TypeScript, and JavaScript. Mastery of these ideas is crucial for leveraging language features and using external libraries that depend on them. It also ensures that your code is readable and maintainable by others. Let's dive in.

Class

A class is a blueprint or template. It defines the properties and methods that an object created from the class will have. Think of it as a mold for creating instances.

For example, in an e-commerce system, we might have a class for products:

class Product {
    protected string $name;
    protected float $price;
    
    function __construct(string $name, float $price) {
        $this->name = $name;
        $this->price = $price;
    }
    
    function applyDiscount(float $percentage) {
        $this->price -= $this->price * ($percentage / 100);
    }
}

Here, the Product class has attributes $name and $price, and a method applyDiscount.

Object

An object is an concretization of a class. It's a concrete entity created using the blueprint provided by the class.

For example:

$newProduct = new Product('Laptop', 999.99);

In this case, $newProduct is an object of the Product class, representing a specific product with a name and a price.

Instance

Instances are specific realizations of a class. When you create an object, you instantiate the class.

For example:

$laptop = new Product('Laptop', 999.99);
$smartphone = new Product('Smartphone', 499.99);

Here, $laptop and $smartphone are instances of the Product class.


Objects vs. Instances in Practice

From a structural programming perspective, there's no significant difference between an object and an instance. They are often used interchangeably in modern programming languages. While some languages (like Swift, C, C++, and C#) might differentiate between them, for most purposes in PHP, JavaScript, and TypeScript, they are the same.


InstanceOf Checks

Many languages provide an instanceOf operator to check if an object is an instance of a specific class.

For example in PHP:

$product = new Product('Laptop', 999.99);
$this->assertInstanceOf(Product::class, $product); // true
$notAProduct = 'Laptop';
$this->assertInstanceOf(Product::class, $notAProduct); // false
$this->assertNotNull($product); // true

Remember, the new keyword is always used to create an object from a class.

Interface

An interface is a contract that ensures a class implements specific methods. It allows you to write more abstract and flexible code.

For example:

interface Item {
    function applyDiscount(float $percentage);
}

class Product implements Item {
    protected string $name;
    protected float $price;
    
    function __construct(string $name, float $price) {
        $this->name = $name;
        $this->price = $price;
    }
    
    function applyDiscount(float $percentage) {
        $this->price -= $this->price * ($percentage / 100);
    }
}

Here, the Item interface guarantees that any class implementing it will have the applyDiscount method.

Interfaces allow for polymorphism:

class Service implements Item {
    protected string $description;
    protected float $rate;
    
    function __construct(string $description, float $rate) {
        $this->description = $description;
        $this->rate = $rate;
    }
    
    function applyDiscount(float $percentage) {
        $this->rate -= $this->rate * ($percentage / 100);
    }
}

$items = [new Product('Laptop', 999.99), new Service('Consulting', 150.00)];
foreach ($items as $item) {
    $item->applyDiscount(10);
}

The Item interface ensures that both Product and Service classes have the applyDiscount method, enabling the generic handling of these different types.

Abstract Classes

Abstract classes provide a way to enforce certain properties or methods in derived classes while also allowing shared functionality. They can include both concrete methods and abstract methods that must be implemented by subclasses.

For example:

abstract class BaseProduct {
    protected string $name;
    protected float $price;
    
    function __construct(string $name, float $price) {
        $this->name = $name;
        $this->price = $price;
    }
    
    abstract function applyDiscount(float $percentage);
    
    function getDescription() {
        return $this->name . " costs " . $this->price;
    }
}

class Product extends BaseProduct {
    function applyDiscount(float $percentage) {
        $this->price -= $this->price * ($percentage / 100);
    }
}

Use an abstract class when you need to ensure certain attributes and methods are present in all derived classes, but you also want to share some common functionality.

Trait

Traits are reusable chunks of code that can be included in multiple classes. They are useful for including common functionality without using inheritance.

For example:

trait Logger {
    function log(string $message) {
        echo $message;
    }
}

class Product {
    use Logger;
    
    protected string $name;
    protected float $price;
    
    function __construct(string $name, float $price) {
        $this->name = $name;
        $this->price = $price;
    }
    
    function applyDiscount(float $percentage) {
        $this->price -= $this->price * ($percentage / 100);
        $this->log("Applied discount of $percentage%");
    }
}

In PHP, the use keyword inside a class indicates that the class is incorporating a trait. This allows Product to use the log method from the Logger trait.

Types (TypeScript)

In TypeScript, types provide a way to ensure objects have a certain structure. Unlike interfaces, which guarantee that classes implement specific methods, types can be applied to any object.

For example:

type Product = {
    name: string,
    price: number
}

const laptop: Product = { name: 'Laptop', price: 999.99 };

Here, the Product type guarantees that any object assigned to laptop has the name and price properties with the correct types.

Types can also ensure that specific methods are present:

type ProductWithDiscount = {
    name: string,
    price: number,
    applyDiscount: (percentage: number) => void
}

const laptop: ProductWithDiscount = { 
    name: 'Laptop', 
    price: 999.99,
    applyDiscount: (percentage: number) => {
        this.price -= this.price * (percentage / 100);
    }
};

While types can't enforce that a function behaves in a particular way, they ensure the function's presence and structure.

Understanding these core OOP concepts is crucial for writing clear, maintainable code that leverages the full power of PHP, TypeScript, and JavaScript. Whether you're using classes, objects, instances, interfaces, abstract classes, traits, or types, these tools help you create robust, reusable, and scalable code.

Discover and read more posts from Tony Reijm
get started