Parâmetros e seus tipos definindo as dependências injetadas em um objeto
Neste artigo será mostrada como a parametrização é parte essencial para injetar as depêndencias, essa é a continuação do artigo anterior sobre interfaces com o exemplo da interface Videogame
.
A parametrização de objetos e os tipos definidos como parâmetro
Ao parametrizar objetos, o conceito de Type Hinting é essencial, já que definir os tipos como parâmetros nos métodos das classes é fundamental na prática que norteia a injeção de depência.
Parametrizar objetos usando tipos também é algo que envolve uma parte mais conceitual, pois geralmente envolve interfaces (ou classes abstratas), que são defininidas como tipos esperados para serem passados como parâmetro, que na prática vão ser as implementações dessas mesmas interfaces (ou classes abstratas).
Voltando ao exemplo do vídeogame
Se voltarmos para o exemplo prático do artigo anterior, uma pessoa iria jogar o videogame e utilizar a operação de ligar o videogame. Segue uma classe para representar essa pessoa, essa classe vai utilizar a interface Videogame
que contém o método ligar
.
<?php
class PessoaQueJogaVideogame
{
private $videogame;
public function __construct(
Videogame $videogame
){
$this->videogame = $videogame
}
public function jogar(): void
{
try {
$this->videogame->ligar();
} catch (Exception $e) {
echo 'Parece que o videogame não ligou.';
}
}
}
Como a classe PessoaQueJogaVideogame
define a interface Videogame
como parâmetro esperado no seu construtor, o Type Hinting é feito com essa interface como tipo definido (o tipo que é esperado como parâmetro). Com isso, é possível trocar de implementação a qualquer momento livremente, pois esperar uma interface como parâmetro permite que qualquer implementação dessa interface seja passada nesse parãmetro. Por exemplo:
<?php
/**
*
* Passando a implementação MeuVideoGameObsoleto
* da interface para a classe PessoaQueJogaVideogame
*
*/
$pessoaQueJoga = new PessoaQueJogaVideogame(
new MeuVideoGameObsoleto
);
// Jogando com videogame velho.
$pessoaQueJoga->jogar();
/**
*
* Passando a implementação VideoGameNovo
* da interface para a classe PessoaQueJogaVideogame
*
*/
$pessoaQueJoga = new PessoaQueJogaVideogame(
new VideoGameNovo
);
// Jogando com videogame novo.
$pessoaQueJoga->jogar();
Devido a essa flexibilidade de trabalhar com a interface, a classe PessoaQueJogaVideogame
pode receber tanto uma instância da classe MeuVideoGameObsoleto
quanto uma instância da classe VideoGameNovo
ou qualquer outra nova implementação criada que implemente a interface Videogame
, pois a possibilidade de criar implementações é infinita.
Juntando as práticas & conceitos mostrados até aqui (e chegando na injeção de dependência)
O que aconteceu no exemplo mostrado foi que a classe PessoaQueJogaVideogame
está dependendo de um parâmetro que define uma interface como tipo esperado. Essa parametrização tendo uma interface como tipo está abstraindo os detalhes de implementação (de como o videogame funciona), pois a interface oculta esses detalhes ao expor apenas a operação (o método ligar
) de forma abstraida (sem implementação definida).
Com isso diferentes implementações dessa interface poderão ser passadas através desse parâmetro definido, o que gera a liberdade para trocar de implementação. E essa liberdade é o beneficio de ter o baixo acoplamento ao trabalhar com interfaces. É o beneficio que se ganha ao criar um código flexivel. Definir interfaces como os tipos que são esperados dos parâmetros é uma das práticas essenciais (e bastante difundidas na orientação a objetos) para ter baixo acoplamento no código.
Basicamente, tudo é juntar os conceitos de abstração e interface com a parâmetrização de objetos. Toda a parametrização de objetos feita nesse artigo é um exemplo prático do conceito de injeção de dependência (com a dependência injetada no método construtor da classe PessoaQueJogaVideogame
e essa dependencia sendo a interface Videogame
).
ver todos os posts