Alura > Cursos de Programação > Cursos de PHP > Conteúdos de PHP > Primeiras aulas do curso PHP: use Interfaces, Namespaces, Traits e Exceções

PHP: use Interfaces, Namespaces, Traits e Exceções

Corrigindo a modelagem - Apresentação

Olá, pessoal! Boas-vindas à Alura. Sou o Vinicius Dias e vou guiar você nesse curso de Orientação a Objetos com PHP.

Audiodescrição: Vinicius Dias se identifica como um homem branco. Possui cabelos curtos e escuros. No rosto, possui bigode e cavanhaque. No corpo, veste uma camisa em um tom roxo rosado, com a inscrição "PHP Women" (Mulheres PHP, em inglês).

Para quem é este curso?

Se você já está estudando um pouco de PHP, já conhece a sintaxe e tem uma noção de orientação a objetos, esse curso é para você.

Nele, vamos entender melhor alguns princípios, evoluindo o sistema que temos feito nos cursos anteriores, o ScreenMatch.

Conhecendo o projeto

O ScreenMatch é uma plataforma de streaming que estamos construindo ainda na linha de comando, sem criar interfaces web, para focarmos no aprendizado da parte de orientação a objetos.

A ideia é ter uma plataforma de streaming com informações de filmes, séries, com seus episódios e outras informações.

Já que vamos evoluir o projeto que temos feito anteriormente, se você não fez os cursos anteriores, haverá um exercício de preparação de ambiente entre as atividades desta aula para você baixar o projeto no estado em que ele finalizou o último curso. A partir daí, vamos evoluí-lo.

O que aprenderemos?

Nesse curso, vamos aprender bastante sobre:

Se durante qualquer parte desse curso, algo não ficar muito claro, não hesite em abrir um tópico no fórum do curso ou entrar no servidor do Discord, onde essa conversa será mais dinâmica.

Além de fazer perguntas, recomendamos que você ajude outras pessoas e responda perguntas, porque essa é uma ótima forma de fixar o aprendizado.

Esperamos que aproveite bastante esse conteúdo. Nos veremos no próximo vídeo para colocar a mão na massa, escrevendo um código orientado a objetos com PHP.

Corrigindo a modelagem - Removendo a implementação

Vamos relembrar rapidamente onde paramos no curso anterior: criamos uma CalculadoraDeMaratona para incluir diversos títulos que podemos assistir e, no final, ela retorna a duração necessária dessa maratona.

Recapitulando o código

Vamos executar esse código novamente, acessando o projeto pelo Visual Studio Code e abrindo um terminal. Nele, vamos executar o comando abaixo, onde index.php é o nome do arquivo que possui a execução.

php index.php

Como resultado, temos o cálculo de 6.180 minutos para assistir uma série ou um filme.

Para essa martona, você precisa de 6180 minutos

Além de implementar esse código, despertamos uma dúvida. Comentamos sobre um problema incômodo na classe Titulo, que serve como base tanto para filme quanto para série. Chamamos esse tipo de classe de classe base, pois será especializada.

Na classe Titulo, temos um método chamado duracaoEmMinutos que serve para incluir a duração da maratona em minutos para cada título incluído na classe CalculadoraDeMaratona. Com isso, obrigamos quem estender a classe Titulo a ter o método duracaoEmMinutos.

No entanto, na classe do Titulo em si, que é mais abstrata e não define bem o que é esse título, não sabemos como calcular a duração em minutos, porque esse cálculo será diferente entre um filme, uma série que tem episódios e uma minissérie, que não tem temporadas.

Por isso, colocamos uma implementação falsa padrão no Titulo, só para ter algo. E isso é um problema.

Vamos imaginar que implementaremos uma minissérie ou um documentário de três episódios, por exemplo. Ela não terá temporadas, portanto, o cálculo será diferente, mas também não temos o atributo de duração em minutos em um único título, como é o caso de um filme.

Já que o cálculo entre série e filme será diferente, devemos escrever uma nova classe. Contudo, se escrevermos a classe Minisserie, herdando de Titulo, e acidentalmente esquecermos de sobrescrever o método duracaoEmMinutos, o cálculo dessa maratona retornará o valor da duração zerado.

Logo, temos um problema de modelagem. Não deixamos evidente que o elemento que estende Titulo precisa tomar uma ação.

Vamos resolver essa situação.

Criando uma classe abstrata

No arquivo Titulo.php, dentro do caminho de pastas "src > Modelo", temos o método duracaoEmMinutos que não é real, mas sim uma ideia de cálculo abstrata. Sabemos que todo título possui uma duração em minutos, mas que a implementação disso será diferente em cada classe.

Em relação ao termo abstrato, abordamos anteriormente a abstração como um dos pilares da orientação a objetos e descobrimos que existem outros significados para a abstração.

Nesse sentido, dizer que esse método é abstrato significa que ele ainda não tem implementação. Quem for especializar a classe Titulo vai precisar implementá-lo.

Vamos remover a implementação do método duracaoEmMinutos.

Titulo.php:

class Titulo
{
    // Código omitido
    
    public function duracaoEmMinutos(): int;
}

Ao salvar esse código, o Visual Studio Code vai apontar um erro. Se passarmos o mouse em cima dele para entender, veremos uma mensagem indicando que um método não abstrato precisa conter um corpo, ou seja, uma implementação.

Entretanto, queremos tornar esse método abstrato. Para isso, adicionaremos a palavra abstract antes do public. Poderíamos adicioná-la depois do public, mas por convenção colocamos no início.

class Titulo
{
    // Código omitido
    
    abstract public function duracaoEmMinutos(): int;
}

Com isso, esse método se torna abstrato. A duracaoEmMinutos agora é uma ideia que temos e a partir disso, cada classe que especializar o Titulo precisará implementar esse método necessariamente.

Se a classe Serie não tiver esse método ou escrever esse método com o nome errado, por exemplo, teremos um erro na execução do PHP.

Extensões e IDEs para PHP

Um detalhe importante é que existem funcionalidades que IDEs vão trazer para nós e que não temos no Visual Studio Code. Existem extensões para dar dicas em relação ao PHP no Visual Studio Code, como PHP Intelephense e PHP IntelliSense , mas as IDEs podem fornecer informações mais interessantes.

Vamos abrir nosso projeto em uma IDE chamada PhpStorm, mas você não precisa tê-la. Vamos simplesmente verificar como seria usá-la.

Em seu interior, ao acessar esse método abstrato que criamos, repararemos que a IDE mostra à sua esquerda um ícone de círculo com uma seta para baixo. Quando temos um método sobrescrito por outras classes, mesmo que não seja abstrato, a IDE mostra esse ícone que, ao ser clicado, informa quais métodos o sobrescrevem.

O contrário também é verdadeiro. Se temos um método sobrescrito, ele mostra um ícone de círculo com uma seta para cima, mostrando qual implementação ele está sobrescrevendo.

Agora que temos um método abstrato, o duracaoEmMinutos, se acessarmos o arquivo Filme.php, por exemplo, e esse método não estiver presente, a IDE vai informar um erro no início da classe Filme, dizendo que ela precisa implementar duracaoEmMinutos.

Existem outras coisas que uma IDE nos traz. Por exemplo, temos o atributo #[Override], comentado no curso anterior, que indica que é um método que estamos sobrescrevendo.

Se voltarmos para Titulo.php e adicionarmos esse atributo acima do método duracaoEmMinutos, tendo escrito o nome desse método errado ou algo do tipo, ele nos informará que esse método deveria ser uma sobrescrita, mas não está sobrescrevendo nada.

Titulo.php:

class Titulo
{
    // Código omitido
    
    #[Override]
    abstract public function duracaoEmMinutos(): int;
}

Podemos concluir que uma IDE nos auxilia e traz algumas facilidades que um editor de código, como o Visual Studio Code, não traz.

Testando o método abstrato

Voltando ao assunto da aula, temos agora, na classe Titulo, um método abstrato. Como ele é abstrato, tanto Serie quanto Filme precisam sobrescrever esse método.

Vamos adicionar o #[Override] também no método duracaoEmMinutos presente em Serie, para seguir esse padrão de utilizar bem os atributos.

Serie.php:

class Serie extends Titulo
{
    // Código omitido
    
    #[Override]
    public function duracaoEmMinutos(): int;
    {
        return $this->temporadas * $this->episodiosPorTemporada * $this->minutosPorEpisodio;
    }
}

Com isso, temos duracaoEmMinutos na Série e no Filme, e ambos estão sobrescrevendo.

Contudo, ainda temos um erro aparecendo no Titulo. Vamos tentar executar esse código. Acessando a aba do terminal, vamos limpar a tela e executar de novo o comando abaixo.

php index.php

Com isso, teremos um erro dizendo que a classe Titulo tem um método abstrato e precisa ser declarada como abstrata ou, então, implementar esses métodos.

A seguir, vamos entender o que é essa ideia de tornar a classe abstrata e a teoria de classes abstratas.

Corrigindo a modelagem - Nova abstração

No último vídeo, nos deparamos com o seguinte erro apontado no terminal: a classe Titulo contém um método abstrato. Por isso, precisa ser declarada como abstrata ou implementar o restante dos métodos (duracaoEmMinutos).

Conhecendo as classes abstratas

Isso quer dizer que a classe Titulo está incompleta. Temos uma classe que não possui todas as implementações para que possa ser instanciada. Ou seja, a classe Titulo, assim como o método duracaoEmMinutos, é uma classe abstrata, na qual ainda não temos uma ideia concreta, já que o contrário de abstrato é concreto.

Nesse momento, não temos uma ideia concreta do que é um título. Isso faz sentido quando trazemos para o mundo real, para o nosso domínio e para o Screen Match (nossa plataforma de streaming), porque quando acessamos a seção de títulos, temos séries ou filmes — temos uma seção para filtrar por série ou por filme, e conseguimos assistir uma série ou um filme.

Ou seja, não existe o conceito genérico de título no Screen Match.

Vamos pensar novamente no contexto do banco. Podemos abrir uma conta corrente, uma conta poupança, uma conta universitária ou uma conta de investimentos, mas não podemos abrir simplesmente uma conta, sem informar qual tipo ela é. Ou seja, essa ideia mais genérica ou abstrata precisa ser especificada no código também.

Nesse caso, Titulo passa a ser uma classe abstrata. Portanto, antes da palavra class, da classe Titulo, vamos adicionar também o abstract.

Titulo.php:

abstract class Titulo
{
    // Código omitido
}

Características da classe abstrata

Entre as características de classes abstratas, elas podem ter métodos abstratos, os quais sabemos que serão implementados pelas classes filhas ou derivadas.

No nosso caso, as classes derivadas de Titulo são Serie e Filme. Ou seja, se temos um método duracaoEmMinutos como abstrato, Filme e Serie precisam implementar esse método ou também precisam ser abstratas, e quem estender Serie ou Filme vai realizar essas implementações.

Basicamente, se a classe for concreta e estender ou herdar de Titulo, vai precisar implementar duracaoEmMinutos.

Outra característica de classes abstratas é que elas não podem ser instanciadas. Vamos abordar um exemplo com um código.

Vamos abrir o terminal novamente e digitar o seguinte comando para entrar no terminal interativo e executar códigos sem precisar criar um arquivo:

php -a

Em seguida, vamos fazer um require de src/modelo/Titulo.php entre aspas simples para incluir o arquivo de Titulo.

require 'src/modelo/Titulo.php';

Depois, vamos tentar criar um novo Titulo. Para isso, vamos precisar também do gênero, portanto, vamos incluir o arquivo de Genero.

require 'src/modelo/Genero.php';

Por fim, vamos tentar fazer $título = new Título e passar todos os parâmetros entre parênteses: Nome entre aspas simples, o ano de lançamento 2024 e o Genero::Acao.

Estamos tentando criar um novo Titulo.

$título = new Título(Nome, 2024, Genero::Acao);

Quando apertamos "Enter" e tentamos instanciar, temos o aviso de um erro dizendo que o erro não foi tratado e não é possível instanciar a classe abstrata Titulo.

Vamos digitar quit para sair do terminal interativo.

quit

Uma classe abstrata não pode ser instanciada. Ou seja, nunca teremos somente Titulo sendo instanciado no código.

Apesar disso, Titulo é um tipo. Conseguimos receber parâmetros e retornar valores do tipo Titulo, mas a variável em si (ou seja, o valor real) precisa ser de alguma classe concreta que herda de Titulo.

Serie e Filme são classes que herdam de Titulo, portanto, vão funcionar. Afinal de contas, ambos estão sobrescrevendo o método duracaoEmMinutos.

Já a classe CalculadoraDeMaratona, pode receber uma instância de Titulo sem problemas, mas a instância em si será um Filme, uma Serie ou outra coisa que herde de Titulo. Com isso, temos uma classe que não pode ser instanciada, mas é herdada e obriga a implementação de duracaoEmMinutos a quem herdar essa classe e for uma classe concreta.

Dessa forma, garantimos que todo Titulo possui uma duracaoEmMinutos - tanto é que conseguimos chamar esse método em CalculadoraDeMaratona sem problemas -, mas não temos uma implementação incorreta.

Se amanhã ou depois alguém for implementar qualquer tipo que herde de Titulo, a IDE vai avisar que é necessário implementar esse método. E se a pessoa não utilizar uma IDE, ela vai ver um erro na hora de executar, informando que Titulo exige que a implementação de duracaoEmMinutos.

Assim, as coisas ficam mais evidentes e não precisamos ficar procurando o motivo do problema.

Essa é o conceito de classes e métodos abstratos no PHP.

Falamos bastante sobre heranças, e mencionamos outros tipos de Titulo, mas podemos ter algo no modelo que não seja um Titulo - por exemplo, um episódio. E podemos ter avaliações de episódios também.

A seguir, vamos verificar como podemos fazer essa modelagem e avaliar algo que não é Titulo, transformando o formato da avaliação de notas que vão de 0 a 10 para estrelas que vão de 1 a 5.

Sobre o curso PHP: use Interfaces, Namespaces, Traits e Exceções

O curso PHP: use Interfaces, Namespaces, Traits e Exceções possui 117 minutos de vídeos, em um total de 47 atividades. Gostou? Conheça nossos outros cursos de PHP em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda PHP acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas