Curso POO com PHP: #6 - Métodos estáticos e classes abstratas

Seja muito bem-vindo de volta, jovem escoteiro. Seguindo nossa jornada em busca de masterizar a Orientação a Objetos com PHP, vamos falar agora de métodos estáticos.

Quando definimos uma propriedade ou um método de uma classe como estático, ele automaticamente se tornam acessíveis sem a necessidade de instanciar a classe.

Veja o exemplo abaixo

<?php

class Financeiro {
    protected $totalFaturado;

    public function definirTotalFaturado($totalFaturado)
    {
        $this->totalFaturado = $totalFaturado;
    }

    public function calcularImposto($taxa)
    {
        return $this->totalFaturado * $this->converterParaPercentual($taxa);
    }

    public function converterParaPercentual($valorInteiro)
    {
        return $valorInteiro / 100;
    }
}

$financeiro = new Financeiro();
$financeiro->definirTotalFaturado(900);
echo $financeiro->calcularImposto(20);

Se analisarmos bem, o método converterParaPercentual da classe Financeiro é bastante útil e seria legal se pudéssemos utilizar ele em outros locais que não apena na classe Financeiro. Porém, como ele é um método da class Financeiro, ela só existe naquele contexto. Mas existe uma forma de contornar esse "problema".

Static

<?php

class Financeiro {
    // outros métodos e propriedades...

    public static function converterParaPercentual($valorInteiro)
    {
        return $valorInteiro / 100;
    }
}

echo Financeiro::converterParaPercentual(89);

No exemplo acima, o método converterParaPercentual recebeu a palavra reservada static ao usarmos essa palavra reservada o PHP entende que deve tratar esse método como estático, assim sendo não é mais necessário criar uma instância dessa classe para poder utiliza-lo, visto que o método em questão passa a ser acessível a partir da própria classe.

Entretanto é interessante frisar que quando estamos acessando um método ou propriedade estática a partir da classe, não utilizamos o "->", mas sim o "::".

Vamos a outro exemplo

<?php

class Financeiro {
    // outros métodos e propriedades...

    public static function imprimirComoPercentual($valorInteiro)
    {
        echo self::converterParaPercentual($valorInteiro);
    }

    public static function converterParaPercentual($valorInteiro)
    {
        return $valorInteiro / 100;
    }
}

echo Financeiro::imprimirComoPercentual(89);

Perceba que quando estamos dentro de um método estático e precisamos acessar outro método estático ou uma propriedade estática, não podemos utilizar o $this, para esses cenários você deve substituir o $this por self e substituir o "->" por "::".

Abstract

Existem diversas situações em que uma classe não deveria ser instanciada. Pense numa Conta Corrente e em um Conta Poupança, mesmo sabendo que ambas são Contas Bancárias, faz sentido que alguém chegue no banco e tenha o seguinte diálogo:

  • Cliente: Boa tarde, gostaria de abrir uma Conta Bancária
  • Gerente: Ok, você quer uma Conta Corrente ou uma Conta Poupança?
  • Cliente: Nem uma, nem outra, eu quero apenas uma Conta Bancária
  • Gerente: Não entendi. Você quer uma Conta Conjunta, um Conta Empresarial, etc...?
  • Cliente: Não, eu quero apenas uma Conta Bancária

Conta Bancária é algo abstrato, enquanto uma conta Corrente ou uma Conta Poupança, são conceitos mais próximos da realidade.

Como outro exemplo eu convido você a pensar em um Felino sem que pra isso você pense num Leão, Tigre, Gato domestico, etc... É possível criar um Felino, que não seja um Leão, Gato, Tigre, Onça, etc... Ou seja, que seja apenas um Felino? Acredito que não...

Mas como podemos fazer isso no PHP?

<?php

abstract class ContaBancaria {
    private $agencia;
    private $numero;
    private $titular;

    public function __construct($agencia, $numero, $titular)
    {
        $this->agencia = $agencia;
        $this->numero = $numero;
        $this->titular = $titular;
    }

    public function sacar() {
        // ...
    }

    public function depositar() {
        // ...
    }
}

class ContaCorrente extends ContaBancaria {
    public function realizarTransferencia() {
        // ...
    }
}

class ContaPoupanca extends ContaBancaria {
    public function calcularRendimento() {
        // ...
    }
}

$contaCorrente = new ContaCorrente(1234, "6789-1", "Mariana Silva");
$contaPoupanca = new ContaPoupanca(1234, "6789-1/500", "Pedro da Cunha");

Perceba o uso da palavra reservada abstract, essa palavra indica ao PHP que essa classe é abstrata e não deve ser possível instanciá-la, ou seja, ela serve apenas de base para que outras classes possam estendê-la.

E ai, tranquilinho até aqui? Lembre-se sempre que se tiver alguma dúvida você pode postar aqui na seção de comentários. Até a próxima, escoteiro!!!