Fácil PHP

Trait de saudação

Enunciado

Crie uma trait Saudacao com o método dizerOla() que retorna "Olá, " . $this->nome. Depois, crie a classe Pessoa que usa a trait e tem a propriedade $nome definida no construtor. Instancie Pessoa('Maria') e imprima o retorno de dizerOla().

Requisitos

  • A trait Saudacao deve ter o método dizerOla().
  • A classe Pessoa deve usar a trait com use Saudacao;.
  • A classe Pessoa deve ter propriedade $nome acessível pelo método da trait.
  • A saída deve ser exatamente Olá, Maria.

Código inicial

<?php
// Defina a trait Saudacao e a classe Pessoa

$p = new Pessoa('Maria');
echo $p->dizerOla();

Saída esperada

Olá, Maria
Ver dica

Dentro da trait, $this se refere à instância da classe que a usa. Então você pode acessar $this->nome diretamente.

Mostrar solução
<?php
// Trait com o método de saudação
trait Saudacao {
    public function dizerOla(): string {
        return "Olá, " . $this->nome;
    }
}

// Classe que usa a trait
class Pessoa {
    use Saudacao;

    public function __construct(public string $nome) {}
}

$p = new Pessoa('Maria');
echo $p->dizerOla();

Passo a passo

  1. Declaramos a trait Saudacao com trait Saudacao { ... }.
  2. Dentro dela, o método dizerOla() retorna a concatenação de "Olá, " com $this->nome. O $this será a instância da classe que usar a trait.
  3. A classe Pessoa usa a trait com use Saudacao;.
  4. O construtor promovido define a propriedade pública $nome.
  5. Criamos $p = new Pessoa('Maria') e chamamos dizerOla(), que acessa $this->nome (Maria).
  6. O echo imprime o resultado.

Por que funciona

A trait injeta o método dizerOla() na classe Pessoa como se ele tivesse sido escrito ali. Como $this aponta para o objeto Pessoa, o método consegue acessar a propriedade $nome definida na classe. Isso demonstra o reuso horizontal: a trait não precisa saber qual classe a usará, apenas que ela terá a propriedade esperada.

Erros comuns

  • Esquecer o use Saudacao; dentro da classe: $p->dizerOla() gera erro fatal "Call to undefined method".
  • Declarar a propriedade $nome dentro da trait em vez da classe: embora possível, foge do propósito e pode causar conflitos. Prefira definir na classe.
  • Usar $this->nome sem garantir que a propriedade exista: se a classe não tiver $nome, ocorre aviso de propriedade indefinida.

Outra forma de resolver

Usar um método abstrato na trait para forçar a classe a fornecer o nome:

trait Saudacao {
    abstract public function getNome(): string;
    public function dizerOla(): string {
        return "Olá, " . $this->getNome();
    }
}

Isso é preferível quando a trait precisa de um contrato claro em vez de acessar propriedades diretamente.

Saída esperada

Olá, Maria