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.