Orientação a Objetos

Thailan
9 min readFeb 23, 2021

--

Este é um termo muito utilizado entre a galera de programação, principalmente back-end, e por mais que todos os dias nós usamos em nossos códigos um conceito ou outro, sempre acabamos esquecendo sua definição e até mesmo como aplicar corretamente.

E pra galera que tá começando nessa área, já pensa de cara, “Como assim, representar um objeto do mundo real em códigos?” Que loucura é essa cara?
Pois é, baita loucura, mas facilita e muito nossa vida viu? Então se também quer entender melhor como funciona tudo, é só seguir esse post porque ele é destinado principalmente a você!

Antes de tudo, o código fonte deste post está disponível em meu GitHub, para que possam acompanhar e testar junto.

https://github.com/ThailanHigor/Thailan-Dev-Education

O que é?

Orientação a objetos é um paradigma de programação. Existe a programação orientada a objetos (POO) e a programação estruturada. E baseadas nesses paradigmas algumas linguagens permitem que você programe com base nelas, C#, Java e Python por exemplo são orientadas a objetos, apesar de haver controvérsias ai em relação Python, mas tudo bem. E ai temos Elixir, F# e Scala com seu paradigma de programação funcional.

Por hora, vamos focar na programação orientada a objetos (POO).

Classes e Objetos

Antes de mais nada, precisamos entender o que é uma classe e o que significa um objeto nesse contexto.

Classe é uma estrutura de código que tem como objetivo mapear um objeto do mundo real ou simplesmente uma representação de alguma coisa.

Vamos aos exemplos pra explicar melhor, e sim, será utilizando jogos como exemplo!

Classe Personagem em C#

Se liga que aqui, temos uma classe ou molde chamado Personagem, que é como se fosse um boneco de um jogo. Ele tem as Propriedades (guarda esse termo aí), Nome, Vida e Velocidade. Percebe que ela é um molde porque em um jogo XYZ de RPG por exemplo, um Personagem sempre tem que possuir um Nome, a quantidade de Vida e uma Velocidade? Isso são Propriedades da Classe.

Mas e o Objeto nessa história?

Objeto é quando você instancia uma classe, ou seja, cria-se um novo objeto em memoria que possui o molde de uma classe X.

Se liga só.

Criação de dois Personagens como Objetos

Temos aqui, dois Objetos instanciados, ou seja, criados a partir da nossa classe Personagem, que serviu de molde. Perceba que em um novo jogo foram criados dois personagens com suas propriedades e atributos diferentes entre si, mas novamente, os dois sob um mesmo molde. Isso é Objeto. Agora os dois estão em memória e podem ser usados no resto do código. E assim como esses dois, é possível criar quantos personagens forem necessários, com seus valores diferentes.

E pra finalizar essa parte aí, temos o conceito de Métodos.

Métodos são funcionalidades e/ou ações que uma classe possui.

Voltando ao nosso jogo.

Métodos adicionados ao Personagem

Acrescentei agora, dois Métodos: Subir De Nivel e Morrer.
Pense em Método como se fosse uma funcionalidade ou ação do personagem em si.
Um personagem pode subir de nível, e quando isso acontecer, precisamos mudar as propriedades dele, e dar a ele mais Vida e Velocidade por exemplo.
Então pra isso, basta chamar esse método em nosso Jogo:

Isso porque todo personagem tem essa função/ação. O mesmo ocorre com o Morrer, onde a vida do personagem será diminuída à 0.

Então pra fixar essa parte, um resumo:

Uma Classe é um molde que possui Propriedades e Métodos e que pode ser instanciada em vários Objetos.

Pilares do POO

Ah! Os famosos pilares. Quem nunca ouviu esse termo?
Então, o POO é consolidado em 4 pilares ou princípios base:

Herança, Abstração, Polimorfismo e Encapsulamento.

Quando compreender os conceitos desses 4 nomes estranhos aí, você certamente estará num outro patamar.

Herança

Pense em herança, quase no mesmo principio do Personagem molde explicado acima. Você tem diversos Objetos utilizando o mesmo Molde.

Com herança é semelhante, quando uma classe herda e absorve as características, propriedades e comportamentos de uma outra classe.
Você vai entender melhor agora, ainda utilizando a classe Personagem:

Duas heranças da classe Personagem

O esquema aqui é sempre pensar no É UM. Mago é um Personagem. Guerreiro é um Personagem.
Simples né? E ai, com essa herança agora Mago e Guerreiro, terão todas as propriedades de um personagem normal e ainda cada uma das propriedades especificas adicionais de cada tipo de Personagem:

Propriedades adicionais

Notem, agora não está sendo instanciado mais um Personagem, e sim a classe especifica, Mago e Guerreiro, porque ambas já herdam de Personagem.

Abstração

Pensar em abstração é pensar em algo genérico.
Logo, se tratando de Classes, a ideia é construir uma super classe genérica que vai servir de base para outras. Além das propriedades a abstração permite definir métodos mas sem dizer o que eles precisam fazer, porque isso será de responsabilidade de quem herdar a classe abstrata.

Eu sei, eu sei. Parece confuso né? Mas vamos lá.
Vamos reescrever nossa classe Personagem, utilizando agora os conceitos de abstração.

Classe Personagem Abstrata

Perceba a adição do termo abstract, que diz agora que a classe é abstrata e também um método abstrato chamado Ataque. Mas porque isso?
Tornamos agora essa classe mais genérica possível, pois pensa comigo, um Mago tem um Ataque diferente de um Guerreiro né?
Afinal um utiliza sua magia outro sua força. Portanto é de responsabilidade das classes Mago e Guerreiro, fazerem funcionar seus respectivos ataques como eles devem ser!
E por isso a classe abstrata diz que, um Personagem TEM que ter uma função/método de ataque porém não diz como tem que funcionar precisamente. Em outras palavras estamos obrigando a classe que implementar à construir esse método.

Ah, é importante ressaltar que uma classe Abstrata não pode ser mais instanciada diretamente. Ela agora só pode ser Herdada, do contrário você receberá um erro de sintaxe.

Erro de sintaxe

E agora pra finalizar essa parte de Abstração, precisamos implementar o método de Ataque agora exigido pela superclasse Personagem.

Implementação de cada método abstrato

Viu? Simples e prático!
Note a palavra reservada override, ela indica que o método descrito é uma sobrescrita de um método que está sendo herdado, ou seja, justamente nosso método de Ataque genérico lá na classe Personagem.

E desta forma, cada classe agora diz exatamente como será seu ataque.

Este é um conceito que as vezes pode ser confuso no dia a dia, mas é muito importante e bastante útil em algumas situações.

Polimorfismo

Este conceito pode ser um pouco mais confuso e semelhante à abstração, mas com os exemplos vai ficar tudo mais fácil.

Polimorfismo pode ser entendido como múltiplos comportamentos para uma classe ou método.

Vamos entender melhor, mas antes mudamos um pouco nosso código da classe abstrata Personagem:

Mudanças na classe Personagem

Adicionamos uma nova propriedade chamada Nível, modificamos o metodo SubirDeNivel e acrescentamos um construtor.

Um construtor de uma classe, é um método, que sempre deve ter o exato mesmo nome da classe e é executado quando instanciamos um novo objeto.

Instanciando usando o construtor

Mas como isso foi possível? Um Personagem novo, por padrão definimos as propriedades de Vida, Velocidade e Nivel. E ai só precisamos dizer o nome do personagem, já que o nome de um novo personagem é você quem escolhe este não pode ser padrão.
Viu como ficou mais fácil instanciar um objeto agora?

O Nível é só uma propriedade nova que colocamos para exemplificar.

E o pulo do gato aqui, é no virtual que não tinha antes . E ai começa o polimorfismo.

Lembre-se antes que a classe Personagem é Abstrata e será implementada pelas outras. Portanto herda consigo todos os comportamentos e propriedades.

Temos o nosso método padrão SubirDeNivel. Dizemos que todo personagem quando subir de nivel vai ganhar 20 de vida, 5 de velocidade e 1 nível.

Porém quando deixamos o virtual, estamos dizendo que quem implementar essa classe Personagem, poderá modificar o comportamento desse método.
Veja só:

Polimorfismo de sobrescrita

Ainda utilizaremos o override como no exemplo de abstração, porém, repare que agora, cada uma das classes quando subir de nivel, ganharão propriedades diferentes, ou seja, um guerreiro ganha mais vida que um mago ao subir de nível por exemplo. E é justamente essa a ideia, múltiplos comportamentos para um mesmo método.

O importante aqui é entender que diferente da abstração, não é obrigatório que a classe implemente o método definido como virtual, porque ele possui uma funcionalidade base e padrão caso ninguém à modifique. Veja:

Sem modificações na Classe Guerreiro.

Nesse caso, o Guerreiro passaria a receber os valores padrões de Personagem ao Subir de Nivel.

Temos ainda uma segunda forma de polimorfismo, que é o de sobrecarga. O anterior era de sobrescrita. Isso cai em provas, confia!

Voltemos a nossa classe Mago:

Classe mago modificada

Vemos que agora temos dois construtores numa só classe!
E é justamente isso, a classe permite agora ser instanciada de duas maneiras diferentes. Passando algum nome ou não. Mas como assim?

Vamos supor que inicialmente no meu jogo eu não precise obrigar o jogador a dar um nome ao seu personagem. Então posso deixá-lo criar e jogar e futuramente solicitar que ele dê um nome.
Mas fazendo isso nosso segundo construtor dará um nome padrão para o personagem que será “Mago Iniciante”.

E agora podemos criar o mesmo objeto assim:

Sem passar o nome

Então, seu nome fica sendo Mago Iniciante.
Ou podemos fazer assim, e dar um nome ao personagem:

Passando um nome

Encapsulamento

A ideia aqui é esconder alguns métodos e propriedades que tem comportamentos específicos somente da classe, ou seja, somente a própria classe pode fazer tal ação ou somente quem herda a mesma.
Vamos ao nosso exemplo:

Encapsulamento

A nossa classe Personagem neste momento está assim. Se você for curioso, deve estar se perguntando o que é esse public, protected? E é justamente ai que está o encapsulamento.

Os três tipos principais são public, protected e private.

Public (público): Posso alterar ou usar tal método ou propriedade no meu código inteiro.

Protected (protegido): Somente a própria classe ou quem herdar a classe vai poder usar ou alterar tal método ou propriedade.

Private (privado): Somente a própria classe pode fazer isso.

Perceba que todas as nossas propriedades como Nome, Vida, Velocidade e Nivel estão públicas, então não está legal, porque isso permite ser alterada de qualquer lugar do código. E podemos até adicionar Nivel ou Vida para um personagem por exemplo indevidamente assim ó:

Uso incorreto do encapsulamento

Nada legal né? Como assim adicionar isso à um personagem novo.
Pois é, por isso precisamos encapsular essas coisas para que só a própria classe Personagem saiba como subir de nivel, o quanto de nivel e vida aumentar quando isso acontecer.

Veja como ficou:

Public, protected e private

Agora, temos que o Nome é Publico, porque podemos dar um novo nome ao personagem quando instanciar.

Vida e Velocidade são Protegidas, porque nossas classes Mago e Guerreiro herdam a classe Personagem e precisam modificar essas propriedades como vimos acima no polimorfismo.

E por fim, temos Nivel como Privado. Porque só a classe Personagem precisa saber como evoluir um personagem. E pra isso precisamos definir um método LevelUp que é protegido para ser usado por quem herdar, mas só ele sabe o que fazer, ou seja, atribuir + 1 ao nível do personagem.

E agora se tentarmos burlar isso e adicionar tudo na mão, não será mais possível:

E com isso, fechamos os conceitos base para a orientação à objetos. A partir de agora você poderá se aprofundar mais com o conceito de Interfaces, Modificadores de Comportamento, Composição etc.

Qualquer dúvida ou sugestão, entre em contato comigo por aqui deixando um comentário.

Vlwws!

--

--

Thailan

Desenvolvedor Web, graduado em Sistemas de Informação e pós-graduando em Gestão de Projetos e Inteligência Artificial e Machine Leaning