Menu
Coddy logo textTech

Traits vs. Herança

Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy. Lição 55 de 91.

Agora que você entende como os traits funcionam, vamos esclarecer quando usar traits em vez de herança. Ambos permitem a reutilização de código, mas servem a propósitos diferentes e têm características distintas.

Herança estabelece uma relação de "é um". Uma classe Dog que estende Animal significa que um cachorro é um animal. A classe filha herda a identidade da classe pai e pode ser usada em qualquer lugar onde o tipo pai seja esperado.

Traits fornecem uma capacidade de "tem-um". Quando uma classe usa uma trait Loggable, ela tem funcionalidade de registro — mas não se torna um logger. Traits adicionam comportamento sem mudar o que a classe fundamentalmente é.

<?php
// Herança: Dog É um Animal
class Animal {
    public function breathe(): void {
        echo "Breathing";
    }
}

class Dog extends Animal {
    public function bark(): void {
        echo "Woof!";
    }
}

// Trait: Dog TEM capacidade de logging
trait Loggable {
    public function log(string $msg): void {
        echo "Log: $msg";
    }
}

class Cat extends Animal {
    use Loggable;
}

Principais diferenças a serem lembradas:

AspectoHerançaTraits
Relacionamentoé umtem uma capacidade
LimiteApenas um paiVárias traits permitidas
Verificação de tipoFunciona com instanceofNenhuma identidade de tipo
Mais adequado paraRelacionamentos hierárquicosComportamentos compartilhados entre classes não relacionadas

Use herança quando as classes compartilharem uma identidade comum. Use traits quando classes não relacionadas precisarem da mesma funcionalidade sem fazerem parte da mesma árvore genealógica.

challenge icon

Desafio

Fácil

Vamos criar um sistema de veículos que demonstre quando usar herança em vez de traits. Você criará uma hierarquia de veículos que compartilham uma identidade comum por meio da herança, enquanto adiciona capacidades transversais por meio de traits.

Você organizará seu código em quatro arquivos:

  • Trackable.php: Crie um trait chamado Trackable que forneça a capacidade de rastreamento por GPS. O trait deve ter:
    • Uma propriedade privada $location (string)
    • Um método setLocation(string $location) que armazene a localização atual
    • Um método getLocation() que retorne "Location: [location]"
    Esse trait representa uma capacidade de “tem um”: qualquer veículo pode ter rastreamento, mas ter rastreamento não transforma algo em um veículo.
  • Vehicle.php: Crie uma classe base Vehicle que estabeleça a relação de “é um”. Inclua o arquivo do trait. Use a promoção de propriedades no construtor para definir uma propriedade protegida $brand. Adicione um método describe() que retorne "Vehicle: [brand]". Essa classe deve usar o trait Trackable, pois todos os veículos da nossa frota terão GPS.
  • Car.php: Crie uma classe Car que estenda Vehicle. Inclua o arquivo Vehicle. Use a promoção de propriedades no construtor para aceitar a marca e uma propriedade privada $doors (inteiro). Chame o construtor da classe pai com a marca. Substitua o método describe() para que ele retorne "Car: [brand] with [doors] doors".
  • main.php: Inclua o arquivo Car. Você receberá três entradas: um nome de marca, um número de portas e uma string de localização. Crie uma instância de Car, defina sua localização e, em seguida, imprima duas linhas:
    • O resultado da chamada de describe()
    • O resultado da chamada de getLocation()

Observe como a herança e os traits trabalham juntos aqui: Car é um Vehicle (a herança estabelece a identidade), enquanto Vehicle tem capacidade de rastreamento (o trait adiciona comportamento). Você poderia usar instanceof Vehicle para verificar se algo é um veículo, mas não existe um tipo “Trackable” contra o qual verificar: essa é a principal diferença entre essas duas abordagens.

Experimente você mesmo

<?php
// Arquivo principal - cria e testa a instância de Car

// TODO: Inclua o arquivo Car.php

// Lê as entradas
$brand = trim(fgets(STDIN));
$doors = intval(trim(fgets(STDIN)));
$location = trim(fgets(STDIN));

// TODO: Crie uma instância de Car com brand e doors

// TODO: Defina a localização do carro

// TODO: Imprima o resultado de describe()

// TODO: Imprima o resultado de getLocation()
?>
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de PHP online