Médio PHP

Conflito entre traits

Enunciado

Crie duas traits: A com método falar() que retorna "A" e B com método falar() que retorna "B". Crie a classe C que usa ambas as traits, resolve o conflito usando insteadof para preferir o método de A e cria um alias falarB para o método de B. Instancie C e imprima o retorno de falar() e falarB() em linhas separadas.

Requisitos

  • As traits A e B devem ter o método falar().
  • A classe C deve usar use A, B { ... } com insteadof e as.
  • O método falar() deve retornar A e falarB() deve retornar B.
  • A saída deve ter duas linhas: A e B.

Código inicial

<?php
// Defina as traits A e B e a classe C

$c = new C();
echo $c->falar() . "\n";
echo $c->falarB() . "\n";

Saída esperada

A
B
Ver dica

A sintaxe é use A, B { A::falar insteadof B; B::falar as falarB; } dentro da classe.

Mostrar solução
<?php
trait A {
    public function falar(): string {
        return "A";
    }
}

trait B {
    public function falar(): string {
        return "B";
    }
}

class C {
    use A, B {
        // Usa o método falar() da trait A no lugar do da trait B
        A::falar insteadof B;
        // Cria um alias falarB() para o método falar() da trait B
        B::falar as falarB;
    }
}

$c = new C();
echo $c->falar() . "\n";
echo $c->falarB() . "\n";

Passo a passo

  1. Definimos a trait A com falar() retornando "A".
  2. Definimos a trait B com falar() retornando "B".
  3. Na classe C, usamos use A, B { ... } para importar ambas.
  4. Dentro das chaves, A::falar insteadof B; resolve o conflito: o método falar() da trait A é o que será usado na classe.
  5. B::falar as falarB; cria um alias falarB que aponta para o método falar() da trait B.
  6. Instanciamos C e chamamos falar() (retorna A) e falarB() (retorna B).

Por que funciona

Quando duas traits trazem métodos com o mesmo nome, o PHP não sabe qual usar e emite erro fatal. insteadof diz explicitamente qual método deve prevalecer, e as permite manter o outro método acessível sob um novo nome. Isso dá controle total sobre a composição de comportamentos.

Erros comuns

  • Esquecer o insteadof: use A, B; gera erro fatal "Trait method falar has not been applied, because there are collisions".
  • Usar as sem insteadof quando há conflito: o erro persiste, pois o alias não resolve a colisão.
  • Colocar use A, B { ... } fora da classe: a sintaxe de resolução só é válida dentro da classe.

Outra forma de resolver

Se você não precisa dos dois métodos, basta use A; e ignorar B. Ou, se quiser renomear ambos:

use A, B {
    A::falar as falarA;
    B::falar as falarB;
}

Isso é útil quando nenhum dos nomes originais deve ser mantido.

Saída esperada

A
B