Interfaces and Traits
Defining a contract with an interface, and sharing behavior across classes with traits.
What you'll learn
- Define an interface as a contract of method signatures a class must implement
- Use a trait to share method implementations across otherwise unrelated classes
- Predict the output of a class that both implements an interface and uses a trait
Explanation
A PHP interface declares a set of method signatures a class promises to implement: interface Nameable { public function getName(): string; }. A class opts in explicitly with implements: class Person implements Nameable { ... } -- unlike Go's implicit interfaces, PHP requires this explicit declaration, and PHP will refuse to run if a class claims to implement an interface but is missing a required method.
PHP classes support only single inheritance (extends one parent class at most), which raises a real question: how do you share a chunk of reusable behavior across classes that aren't related by inheritance? PHP's answer is the trait: trait Greetable { public function greet(): string { return "Hello, I'm " . $this->name . "!"; } }, brought into a class with use Greetable; inside the class body. This copies the trait's methods directly into the class, as if you'd written them there yourself -- a form of horizontal code reuse that doesn't participate in the class hierarchy at all.
A trait's methods can reference $this and expect properties (like $name above) to exist on whatever class ultimately uses the trait -- the trait doesn't declare that property itself; it assumes the consuming class provides it, similar to how a mixin works in other languages.
A single class can implement multiple interfaces and use multiple traits at once, which is exactly the flexibility single inheritance alone can't offer -- interfaces describe what a class can do, traits provide how, reusably.
Guided lab
Predict: A trait and an interface together
Read this script and predict exactly what it sends to the browser.
<?php
trait Greetable {
public function greet(): string {
return "Hello, I'm " . $this->name . "!";
}
}
interface Nameable {
public function getName(): string;
}
class Person implements Nameable {
use Greetable;
public function __construct(public string $name) {}
public function getName(): string {
return $this->name;
}
}
$person = new Person("Grace");
echo $person->greet() . "\n";
echo $person->getName() . "\n";Stuck? Get a hint.
Common mistakes
- Forgetting the explicit `implements` keyword -- unlike Go's structural interfaces, PHP requires a class to explicitly declare which interfaces it implements.
- Assuming a trait works like a base class you `extends` -- traits are brought in with `use` inside the class body and don't affect the class hierarchy or `instanceof` checks.
- Writing a trait method that assumes a property exists on the consuming class, without documenting that expectation, leading to confusing errors when a class uses the trait without that property.
Knowledge check
Takeaway
Use `implements` to declare a contract a class fulfills, and `use` (with a trait) to share reusable method implementations across classes that don't share a common parent.
Summary
Interfaces declare method contracts a class must explicitly `implement`; traits (`use TraitName;`) copy reusable methods into a class as horizontal code reuse, independent of inheritance.
References
Your notes
Notes save automatically.
Finished this lesson?
Mark it complete to track your progress and schedule a future review.
AI tutor
The optional AI tutor isn't enabled in this deployment. All lessons, exercises, quizzes, and search work fully without it.