Os pilares da orientação a objeto

Os pilares da orientação a objeto

Os pilares da orientação a objetos são quatro conceitos fundamentais que guiam a programação orientada a objetos. Eles são conceitos essenciais para criar um código modular, flexível, reutilizável e de fácil manutenção. São eles: Abstração, Encapsulamento, Herança e Polimorfismo.

Neste artigo, vamos detalhar cada um e trazer exemplos.

1. Abstração

O paradigma abstração prega que devemos projetar um sistema em diversas partes, separadas e bem definidas, de modo que nos concentremos nos aspectos essenciais, desconsiderando as características menos importantes. Desta forma,  abstrai-se a complexidade do sistema e foca-se em uma determinada parte, que é o tema central naquele momento.

A abstração consiste na representação simples de objetos do mundo real. Uma classe é um tipo de abstração que define um conjunto de propriedades e métodos que representam um conceito particular. A abstração permite que os objetos tenham características comuns e funcionem de maneira consistente.

Vamos aplicar este conceito em um exemplo. Suponha que queremos criar diferentes formas geométricas (círculo, quadrado, triângulo) e calcular sua respectiva área.

<?php
// Classe abstrata para representar uma forma geométrica
abstract class FormaGeometrica {
    // Método abstrato para calcular a área
    abstract public function calcularArea();
}

// Classe para representar um círculo
class Circulo extends FormaGeometrica {
    private $raio;

    public function __construct($raio) {
        $this->raio = $raio;
    }

    public function calcularArea() {
        return pi() * pow($this->raio, 2);
    }
}

// Classe para representar um quadrado
class Quadrado extends FormaGeometrica {
    private $lado;

    public function __construct($lado) {
        $this->lado = $lado;
    }

    public function calcularArea() {
        return pow($this->lado, 2);
    }
}

// Classe para representar um triângulo
class Triangulo extends FormaGeometrica {
    private $base;
    private $altura;

    public function __construct($base, $altura) {
        $this->base = $base;
        $this->altura = $altura;
    }

    public function calcularArea() {
        return ($this->base * $this->altura) / 2;
    }
}

// Uso das classes
$circulo = new Circulo(5);
$quadrado = new Quadrado(4);
$triangulo = new Triangulo(6, 3);

echo "Área do círculo: " . $circulo->calcularArea() . "<br>";
echo "Área do quadrado: " . $quadrado->calcularArea() . "<br>";
echo "Área do triângulo: " . $triangulo->calcularArea() . "<br>";
?>


Neste exemplo, criamos uma classe abstrata FormaGeometrica que define um método abstrato calcularArea(). Em seguida, criamos classes concretas para representar as formas geométricas específicas (círculo, quadrado e triângulo), e cada uma delas implementa o método calcularArea() de acordo com sua fórmula apropriada.

Essa abstração permite que o código que utiliza essas classes interaja com as formas geométricas de maneira independente das implementações específicas de cada forma.

2. Encapsulamento

O encapsulamento é a ideia de esconder os detalhes internos e o funcionamento dos objetos, expondo apenas uma interface controlada para interagir com eles. Isso é feito usando modificadores de acesso nos atributos e métodos, como "private", "protected" e "public", para controlar quem pode acessar e modificar os dados e comportamentos dos objetos.

<?

class Aluno {
    private $nota;
    protected $faltas;
    public $nome;

    public function __construct($nota, $faltas, $nome) {
        $this->nota = $nota;
        $this->faltas = $faltas;
        $this->nome = $nome;
    }

    // Método público que pode ser acessado de qualquer lugar
    public function obtemNome() {
        return "O nome do aluno é " . $this->nome;
    }

    // Método protegido que pode ser acessado apenas dentro da classe e suas subclasses
    protected function obtemFaltas() {
        return "O número de faltas do aluno é " . $this->faltas;
    }

    // Método privado que só pode ser acessado dentro da própria classe
    private function obtemNota() {
        return "A nota do aluno é " . $this->nota;
    }
}

//Nova instância
$novoAluno = new Exemplo(5.5, 10, "Maria");

// Acesso ao atributo público (pode ser acessado de qualquer lugar)
echo "Atributo público: " . $novoAluno->nome . "<br>"; // Sucesso

// Tentativa de acesso aos atributos privado e protegido resultará em erro
echo "Atributo privado: " . $novoAluno->nota; // Erro
echo "Atributo protegido: " . $novoAluno->faltas; // Erro

// Acesso ao método público (pode ser acessado de qualquer lugar)
echo $novoAluno->obtemNome() . "<br>"; // Sucesso

// Tentativa de acesso aos métodos privado e protegido resultará em erro
echo $novoAluno->obtemFaltas(); // Erro
echo $novoAluno->obtemNota(); // Erro


3. Herança

Quando pensamos em herança, imaginamos a relação familiar entre pais, filhos e avós e nas características que são transmitidas de geração para geração. Em orientação a objetos, a herança trata-se de um compartilhamento de atributos e comportamentos entre classes de uma mesma hierarquia, da classe-mãe para as classes-filha. Veja um exemplo na imagem a seguir.


A classe Funcionario é a classe-mãe, da qual aproveitamos suas propriedades (nome, dataNascimento, cpf, setor e salario) e métodos (registraPonto) para criar as classes-filha Professor e Diretor. As classes-filha, além de herdar os pontos anteriormente mencionados, terão algumas características únicas. Para a classe Professor, adicionou-se a inicialização das propriedades disciplina e turma e para Diretor, incluiu-se a propriedade unidade. No caso dos métodos, a classe Professor pode registrar a nota de um aluno, e a classe Diretor pode registrar um novo funcionário na unidade escolar que trabalha.

A herança tem uma grande aplicabilidade, pois ao invés de criarmos estruturas novas, pode-se aproveitar estruturas já existentes.

4. Polimorfismo

Polimorfismo em orientação a objetos é o princípio que permite que duas ou mais classes derivadas de uma mesma superclasse tenham métodos iguais (com mesmo nome e parâmetros), porém comportamentos distintos, redefinidos em cada uma das classes-filha. A seguir temos um exemplo utilizando o jogo de xadrez.

<?

class Peca {
abstract public function mover();
}

?>

<?

class Torre extends Peca {
public function mover() {
  echo "Movimenta em linha reta";
}
}

class Cavalo extends Peca {
public function mover() {
  echo "Movimenta em 'L'";
}
}

class Bispo extends Peca {
public function mover() {
  echo "Movimenta na diagonal";
}
}


class Peao extends Peca {
public function mover() {
  echo "Movimenta para frente";
}
}

Torre->mover(); // Movimenta em linha reta
Cavalo->mover(); // Movimenta em 'L'
Bispo->mover(); // Movimenta na diagonal

Peao->mover(); // Movimenta para frente

?>


O jogo de xadrez tem diferentes peças, e cada peça realiza seu movimento: o peão movimenta para frente, o cavalo movimenta em L, a torre movimenta em linha reta e o bispo em diagonal. Trazendo isso para o princípio do polimorfismo, todos são derivados da classe Peca e tem o método mover, mas cada um se movimenta de uma maneira diferente, tendo o método redefinido na classe-filha (classe Torre, Cavalo, Bispo e Peao).

Conclusão

A orientação a objeto permite que o código reflita os conceitos do mundo real, facilitando a compreensão. Deste modo, é essencial ter um bom entendimento dos seus paradigmas (Abstração, Encapsulamento, Herança e Polimorfismo), para que seja possível desenvolver softwares mais eficientes, organizados e de melhor manutenção.

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.