PHP para Iniciantes: Classes e Objetos - O básico

Agora que eu já te passei uma boa visão sobre a importância de aprender isso, vamos começar a falar sobre como funcionam as classes e objetos no PHP. Mesmo especializando na linguagem, esse é um assunto grande e, por isso, faz sentido apresentarmos em partes.

É de senso comum chamar a primeira de "básico", mas as próximas não são "intermediário" nem "avançado", pois aqui é tudo assunto pra iniciante, né?

E o que nós chamamos de básico é bem simples:

  1. Como declarar uma classe;
  2. O que é e como declarar propriedades ;
  3. O que é e como declarar métodos.

E tem muitas outras coisas pra gente falar e que muita gente chama de básico, mas eu acho que não é bem assim.

Se você der uma espiada na documentação oficial do PHP, também verá a menção de outros recursos que eu já falei em outros artigos e não são tão relevantes assim, logo não irei mencionar. Se você começou a ler meu blog a partir desse artigo, estou me referindo às constantes pré-definidas e métodos mágicos. Recomendo a leitura!

Ok, Kiko, eu já vi alguma dessas coisas básicas em outro artigo?

Sim, quase tudo. Mas eu vou repetir esses pontos para te ajudar a reforçar sua base de conhecimento. Repetição é importante nesse processo, então... Vamos recapitular!

1. Como declarar uma classe

A declaração de classe é similar a qualquer estrutura de controle que agrupa conjuntos de instruções, onde precedimos tudo com a palavra reservada class, atribuímos um nome e depois encapsulamos sua estrutura entre chaves ({ e }), ficando:

<?php
class NossaClasse
{
    // conteúdo da classe
}

Notou que eu escrevi a primeira letra da classe com letra maiúscula? Isso não é uma regra da linguagem, mas uma boa prática. As regras de escrita são as mesmas da escrita de variáveis:

  • só começa com uma letra ou underline;
  • pode ter números.

E o mais importante de tudo é que esse nome precisa fazer sentido quando você for acionar seus recursos. Por exemplo, faz sentido nomear uma classe que gerencia banco de dados de Gerente? Primeiro que o termo correto para o papel seria Gerenciador, segundo que o que o diferencia dos demais é o fato de ser sobre banco de dados. Então não faria sentido algum dar somente esse nome para a classe.

Kiko, eu vi na internet algumas pessoas discutindo se era melhor escrever em inglês ou português... O que você acha?

Eu não acho é nada, rs. Eu defendo que o time tem de definir em conjunto. Se você vai trabalhar sozinho, então reflita bastante sobre quais profissionais poderão trabalhar no seu código no futuro e vise fornecer um código legível para a maioria. Colocando isso em pauta e falando do meu contexto, acho que o inglês deixa o código mais fácil de ler, pois as palavras reservadas são escritas nesse idioma e o PHP foi feito para ter legibilidade semântica. O único lugar onde a mistura de idiomas consegue fazer sentido de algum jeito é nas músicas asiáticas (pode discordar, mas eu gosto de algumas que todos os versos são no idioma da banda e, de repente, vem uma frase em inglês hahaha).

De todo modo, não feche sua mente pensando "só se programa desse jeito", porque isso é uma mentira.

Dito isso, vamos mudar nosso exemplo para:

<?php
class OurClass
{
    // ...
}

2. O que é e como declarar propriedades de uma classe

Propriedades, além de imóveis, também é um termo utilizado para referenciar aquilo que se apropria. Eu acho estupidamente vago, e você?

Mas quando estamos falando de Orientação a Objeto, propriedade é qualquer informação que um objeto pode conter. E por informação, nós estamos falando de tipos de dados primitivos.

Portanto, propriedade aqui é qualquer informação que você desejar atrelar à sua classe. Por exemplo, digamos que você quer construir a classe Caderno. Para fazer isso, você deve refletir: o que um caderno tem que poderia ser diferente dos outros?

  • a. Marca?
  • b. Quantidade de páginas?
  • c. Quantidade de seções?
  • d. Quantidade de páginas por seção?
  • e. Quantidade de figurinhas?
  • f. Tema?

Cada um desses pontos pode ser uma propriedade dessa nova classe. Eu digo pode porque alguma dessas questões podem ser relacionamentos também, o que seria um pouco mais complexo de explicar. Por agora, vamos apenas criar uma classe tendo isso tudo como propriedades:

<?php
class Caderno
{
    public $marca;
    public $page_quantity;
    public $section_quantity;
    public $pages_per_section;
    public $sticker_quantity;
    public $theme;
}

Ué, Kiko... Você criou variáveis dentro da classe?

Basicamente. Isso é uma propriedade. Porém, a forma que coloquei é a pior possível, pois não estou especificando nada além do nome da propriedade e deixando tudo completamente visível. A forma ideal é colocarmos:

  • o tipo de dados primitivos que aceitamos;
  • a visibilidade que precisamos.

Supondo que essas propriedades sejam acessíveis de forma pública, podemos manter cada uma das declarações precedidas pela palavra reservada public. Isso significa que você poderá acessar e alterar a informação a partir de qualquer parte do código. Se você quer que seja acessível somente pela própria clase e outras que herdarem algo dela, então use a visibilidade protected. Se não houver nenhuma necessidade de ter isso acessível de fora da classe, use o private.

Sobre a tipagem, o que for texto será string e o que for quantidade será int.

Vamos reescrever a classe agora?

<?php
class Caderno
{
    private string $marca;
    private int $page_quantity;
    private int $section_quantity;
    private int $pages_per_section;
    private int $sticker_quantity;
    private string $theme;
}

Kiko, por que você deixou tudo private?

Como eu não tenho nenhum uso fora da classe, ainda, convém deixar tudo assim mesmo. A menos que apareça uma real necessidade de modificar a visibilidade, aí sim nós mudamos.

Com isso, nós conseguimos definir propriedades à classe que queremos criar. Porém, temos alguns problemas aqui:

  1. Qual é o valor padrão de cada propriedade?
  2. Como definir um valor inicial quando instanciarmos a classe?

Bem, para determinar um valor padrão na sintaxe que estamos usando, basta chamar o operador de atribuição e colocar o tal valor:

<?php
class Caderno
{
    private string $marca;
    private int $page_quantity = 125;
    private int $section_quantity = 5;
    private int $pages_per_section = 25;
    private int $sticker_quantity = 20;
    private string $theme = "Abstrato";
}

É desnecessário comentar, mas, lembre que o dado padrão precisa respeitar a tipagem que você definiu.

E sobre atribuir os valores iniciais, para isso precisaremos escrever um método mágico usado no processo de construção de um objeto.

3. O que é e como declarar métodos

O método que veremos a seguir é chamado de Construtor e é acionado toda vez que você usar o operador new na sua classe (ex: new Caderno()), mesmo se você não defini-lo.

O nome desse método deve ser escrito dessa forma: __construct, ficando assim:

<?php
class Caderno
{
    private string $marca;
    private int $page_quantity = 125;
    private int $section_quantity = 5;
    private int $pages_per_section = 25;
    private int $sticker_quantity = 20;
    private string $theme = "Abstrato";

    public function __construct()
    {
    }
}

Note que esse método precisa ter a visibilidade public, por isso já a escrevi por padrão. Outros métodos poderiam ter a visibilidade que você precisar. Lembre de nunca dar liberdade demais a um método ou propriedade, use somente o que precisa.

E assim como funções, você pode passar argumentos de entrada e usa-los com as propriedades do novo objeto. Por exemplo:

<?php
class Caderno
{
    private string $marca;
    private int $page_quantity = 125;
    private int $section_quantity = 5;
    private int $pages_per_section = 25;
    private int $sticker_quantity = 20;
    private string $theme = "Abstrato";

    public function __construct(
        string $marca,
        int $page_quantity = 125,
        int $section_quantity = 5,
        int $pages_per_section = 25,
        int $sticker_quantity = 20,
        string $theme = "Abstrato"
    )
    {
        $this->marca = $marca;
        $this->page_quantity = $page_quantity;
        $this->section_quantity = $section_quantity;
        $this->pages_per_section = $pages_per_section;
        $this->sticker_quantity = $sticker_quantity;
        $this->theme = $theme;
    }
}

Notou que eu praticamente repeti toda a assinatura da classe? Bem, no PHP 8 fizeram uma parada muito legal que é a Definição de Propriedade via Constructor (tradução não-literal para constructor property promotion). Tudo isso que eu escrevi pode ser reescrito da seguinte forma no PHP 8:

<?php
class Caderno
{
    public function __construct(
        private string $marca,
        private int $page_quantity = 125,
        private int $section_quantity = 5,
        private int $pages_per_section = 25,
        private int $sticker_quantity = 20,
        private string $theme = "Abstrato"
    )
    {
    }
}

Com o termo de visibilidade escrito antes do argumento, o interpretador sabe que você quer transformar aquele argumento em uma propriedade da classe. No PHP 8.1 ainda veio a opção de somente leitura, isto é, propriedades que funcionam como a visibilidade public mas somente para acessar o dado. Se você tentar sobreescrever, não funcionará.

Enfim, com essa definição toda, você pode, finalmente, instanciar um objeto:

// PHP 8: Argumentos nomeados
$caderno = new Caderno(
    marca: "KG",
    page_quantity: 60,
    section_quantity: 2,
    pages_per_section: 30,
    sticker_quantity: 0,
    theme: "PHP is the best"
);

Em caso de versões anteriores ao PHP, você não poderá indicar o que está populando, apenas seguir a ordem da assinatura dos métodos.

Achou complexo? Foi muita coisa de uma vez?! Bem, isso foi apenas o básico, aquele choque de realidade que sou obrigado a te passar... Mas com certeza iremos ver todos esses tópicos bem mais mastigados nos próximos artigos. Espero não demorar tanto quanto demorei pra lançar esse, hehe.

Curtiu?! Comenta e compartilha! Ainda não segue meu Twitter? Corre lá!! E não deixa de avisar os amigos que o pai de gêmeas está de volta! ;P

Inté!!