DEV Community

Carlos Viana
Carlos Viana

Posted on • Edited on

PHP Orientado a Objetos: Herança ou Composição ?

Herança vs. Composição em PHP 🚗

Na Programação Orientada a Objetos (OOP) em PHP, entender a diferença entre Herança e Composição é essencial para criar sistemas mais robustos, flexíveis e fáceis de manter. Este artigo explora esses conceitos, suas aplicações, vantagens e desvantagens, com exemplos práticos.


Herança

A herança é um pilar fundamental da OOP que permite que uma classe (subclasse ou classe filha) herde propriedades e métodos de outra classe (superclasse ou classe pai). Isso promove reutilização de código, mas pode levar a acoplamento forte entre classes.

No exemplo abaixo, a classe Carro herda da classe Motor e sobrescreve o método ligar para personalizar o comportamento:

<?php

class Motor {
    public function ligar() {
        return "Motor ligado!";
    }
}

class Carro extends Motor {
    public function ligar() {
        return "O motor do carro está ligado!";
    }
}

$carro = new Carro();
echo $carro->ligar(); // Saída: O motor do carro está ligado!
Enter fullscreen mode Exit fullscreen mode

Características da Herança

  • Reutilização de código: A subclasse herda métodos e propriedades da superclasse.
  • Hierarquia fixa: A relação entre classes é rígida, definida no momento da criação.
  • Sobrescrita: Métodos da superclasse podem ser sobrescritos na subclasse.

Limitações

  • Acoplamento forte: Alterações na superclasse podem afetar todas as subclasses.
  • Herança única: PHP não suporta herança múltipla, o que pode limitar a flexibilidade.
  • Complexidade: Hierarquias profundas podem dificultar a manutenção.

Composição

A composição é uma abordagem alternativa que favorece a modularidade. Em vez de herdar, uma classe contém instâncias de outras classes (objetos) que fornecem as funcionalidades necessárias. Isso segue o princípio "tem um" em vez de "é um".

No exemplo abaixo, a classe Carro possui uma instância da classe Motor, delegando a responsabilidade de ligar o motor:

<?php

class Motor {
    public function ligar() {
        return "Motor ligado!";
    }
}

class Carro {
    private Motor $motor;

    public function __construct(Motor $motor) {
        $this->motor = $motor;
    }

    public function ligar() {
        return $this->motor->ligar();
    }
}

$motorV4 = new Motor();
$carro = new Carro($motorV4);
echo $carro->ligar(); // Saída: Motor ligado!
Enter fullscreen mode Exit fullscreen mode

Características da Composição

  • Modularidade: Cada classe tem uma responsabilidade única, facilitando manutenção.
  • Flexibilidade: Permite trocar componentes (ex.: diferentes tipos de motor) sem alterar a classe principal.
  • Desacoplamento: Reduz a dependência entre classes, promovendo um design mais robusto.

Vantagens

  • Facilidade de manutenção: Alterações em um componente (como Motor) não afetam diretamente a classe Carro.
  • Reutilização: Componentes podem ser usados por várias classes.
  • Flexibilidade: Facilita a substituição de componentes, como trocar um MotorV4 por um MotorEletrico.

Limitações

  • Complexidade inicial: Pode exigir mais código inicial para configurar as relações entre objetos.
  • Sobrecarga de objetos: Criar múltiplos objetos pode aumentar o uso de memória em sistemas simples.

Herança vs. Composição: Quando Usar?

Use Herança Quando:

  • Existe uma relação clara de "é um" (ex.: um Carro é um tipo de Veiculo).
  • Você precisa de uma hierarquia simples e bem definida.
  • A superclasse é estável e não mudará frequentemente.

Use Composição Quando:

  • Existe uma relação de "tem um" (ex.: um Carro tem um Motor).
  • Você busca maior flexibilidade e modularidade.
  • O sistema precisa suportar diferentes configurações ou substituições de componentes.

Exemplo Avançado com Composição
Para ilustrar a flexibilidade da composição, considere diferentes tipos de motores:

<?php

interface MotorInterface {
    public function ligar(): string;
}

class MotorV4 implements MotorInterface {
    public function ligar(): string {
        return "Motor V4 ligado!";
    }
}

class MotorEletrico implements MotorInterface {
    public function ligar(): string {
        return "Motor elétrico ligado!";
    }
}

class Carro {
    private MotorInterface $motor;

    public function __construct(MotorInterface $motor) {
        $this->motor = $motor;
    }

    public function ligar(): string {
        return $this->motor->ligar();
    }
}

$motorV4 = new MotorV4();
$carroCombustao = new Carro($motorV4);
echo $carroCombustao->ligar(); // Saída: Motor V4 ligado!

$motorEletrico = new MotorEletrico();
$carroEletrico = new Carro($motorEletrico);
echo $carroEletrico->ligar(); // Saída: Motor elétrico ligado!
Enter fullscreen mode Exit fullscreen mode

Neste exemplo, a interface MotorInterface garante que qualquer motor implemente o método ligar, permitindo que a classe Carro funcione com qualquer tipo de motor, aumentando a flexibilidade.


Tanto a herança quanto a composição têm seus méritos, mas a composição é geralmente preferida em sistemas modernos devido à sua flexibilidade e menor acoplamento. A herança é útil para hierarquias simples e bem definidas, mas pode levar a problemas de manutenção em sistemas complexos. Ao projetar suas classes em PHP, avalie cuidadosamente a relação entre os objetos e opte pela abordagem que melhor equilibra clareza, flexibilidade e manutenibilidade.

Você pode testar os exemplos de código em OneCompiler.

Top comments (0)