Programação Orientada a Objetos

Programação Orientada a Objetos

Um dos maiores erros de quem entra no mundo da programação é querer passar a carroça na frente dos bois. Antes de aprender o Framework da moda ou ir se aventurar em uma nova linguagem de programação, é importante ter em mente os conceitos "básicos" que ajudam a construir um conhecimento sólido e diminuir a curva de aprendizagem ao se deparar com uma nova tecnologia.

Eu ainda não faço computação, então eu busco criar esse conhecimento de maneira autodidata. Recentemente, percebi que uma das lacunas que eu encontrei no meu conhecimento, foi o conceito de Programação Orientada a Objetos. Então resolvi recorrer ao meu grande mestre Professor Gustavo Guanabara, do Curvo em Vídeo para reforçar os confeitos que eu já uso no estágio, mas que muita das vezes não ficavam claros na minha cabeça. O curso é desenvolvido em Java, porém como eu trabalho com Dart, eu decidi reproduzir o aprendizado nas aulas nessa linguagem.

Pois bem, chega de papo, vamos logo para a mão no código.

Vamos iniciar explicando na prática o que é a orientação a objeto. Bora começar?

O que é isso, se você procurar rapidamente no Wikipédia achara: “Programação Orientada a Objetos (também conhecida pela sua sigla POO) é um modelo de análise, projeto e programação de sistemas de software baseado na composição e interação entre diversas unidades de software chamadas de objetos.”

Programação orientada à objetos (POO), surgiu com a finalidade de facilitar a vida de programadores. Na POO, os objetos conversam entre si.

Criada por Alan Kay, um Biólogo e Matemático, que formulou sua “analogia algébrico-biológica” e lançou o postulado de que o computador ideal deveria funcionar como um organismo vivo, isto é, cada “célula” relacionando-se com outras.

“As coisas simples devem ser simples e as coisas complexas, possíveis.” - Alan Kay

Vantagens da programação orientada à objetos:

  1. Confiável
  2. Oportuno
  3. Manutenível
  4. Extensível
  5. Reutilizável
  6. Natural

O que é um Objeto?

Objetos são instâncias de classes, que determinam qual informação um objeto contém e como ele pode manipulá-la. É uma entidade capaz de reter um estado (informação) e que oferece uma série de informações (comportamento) ou para examinar ou para afetar este estado. É através deles que praticamente todo o processamento ocorre em sistemas implementados com linguagens de programação orientada a objetos.

Classe

Uma Classe é uma descrição de um conjunto de objetos que compartilham os mesmos atributos, operações, relacionamentos e semântica. É usada para classificar. Serve como um “molde” para a criação de objetos.

Dica: Para lembrar imagine um projeto de arquitetura no papel.

Nós declaramos uma classe da seguinte maneira:

Não foi fornecido texto alternativo para esta imagem

Vamos utilizar como exemplo a seguinte classe:

Não foi fornecido texto alternativo para esta imagem

Uma classe tem sempre que responder três perguntas:

  1. Que coisas eu tenho?
  2. Que coisa eu faço?
  3. Como estou agora?

Em POO, essas perguntas são representadas da seguinte maneira:

Atributos — propriedades que descrevem um intervalo de Valores que as instâncias da classe podem apresentar. Abstraem os tipos de dados ou estados que os objetos de uma classe Podem abranger.

Dentro dessa classe cachorro temos os atributos desta classe: nome, raça e peso. Esses atributos são as informações que o nosso objeto irá armazenar.

Não foi fornecido texto alternativo para esta imagem

Métodos — implementam serviços que podem ser solicitados por algum objeto da classe para modificar o comportamento. Abstraem algo que pode ser feito com um objeto. Algumas vezes, a chamada a uma operação de um objeto altera os Atributos ou o estado do mesmo.

Definição: Representação de um conjunto de objetos do mundo real. Os métodos são procedimentos ou funções que realizam as ações próprias do objeto.

Assim, os métodos são as ações que o objeto pode realizar. Tudo o que o objeto faz é através de seus métodos, pois é através dos seus métodos que um objeto se manifesta, através deles que o objeto interage com os outros objetos. Sendo mais conhecidos como: Método Construtor, Métodos Get e Set, Métodos do usuário e Método sobrescrito

Agora que o objeto já está definido vamos ver o que um cachorro é capaz de fazer, para definir suas ações as fazemos por meio de funções void que chamamos, quando estão dentro das classes, de métodos:

Não foi fornecido texto alternativo para esta imagem

Objetos —Podemos criar objetos por meio desta classe, ou seja, declará-los ou instanciar nossas classes, portanto, hipoteticamente falando seria "criar as cachorros". Para instanciá-las, fazemos da seguinte forma:

Cachorro cachorro1 = new Cachorro();

Aplicando no código:

Não foi fornecido texto alternativo para esta imagem

Primeiro criamos o tipo, ou seja, será do tipo "Cachorro". Em seguida, definimos o nome "cachorro1", e depois recebe um novo objeto do tipo Cachorro(); que seria uma instancia do objeto. Resumindo estamos criando o cachorro1. Se dermos um print nesse cachorro1, irá aparecer "Instance of Cachorro1'", ou seja, quer dizer que agora o cachorro1 é uma instância da classe Cachorro. Desta forma, já que criamos um cachorro vamos declarar os dados deste cachorro.

Não foi fornecido texto alternativo para esta imagem

Coloca-se o "." para acessar tal atributo. Pode-se, portanto, criar outro cachorro (cachorro2) que será criada da mesma fonte, mas com dados diferentes.

Chamando um método - Para chamar um método utilizamos também o "." e depois o nome do método, conforme abaixo:

Não foi fornecido texto alternativo para esta imagem

Construtores

Construtor Padrão

Para exemplificar, se dermos um print(cachorro1); irá mostrar "Instance of 'Cachorro'", ou seja, é um objeto que está na memória, mas ainda não está construído, completo. Parece muito com uma função a estrutura do construtor.Para declarar um construtor, primeiramente vamos para dentro do escopo da classe Cachorro e pegamos o nome desta classe e a declaramos, caso não declaremos, ele irá declarar um escondido, não é obrigado a declarar um construtor vazio (ex. Cachorro();), vejamos o exemplo:

Não foi fornecido texto alternativo para esta imagem

O construtor Cachorro(String nome, String raca, double peso) {} pega o nome, raça e peso declarados acima dele.

A pergunta é: como colocar nome (da classe Cachorro) = nome (do construtor)? para isso existe a palavra this que especifica um atributo (variável) do nosso objeto (a variável declarada no início da classe Cachorro) e não do nosso parâmetro do construtor Cachorro.

Assim, this traduzindo seria 'este', mas o que isso significa aí no construtor? quer dizer que 'nesta classe queremos acessar tal atributo', this.nome, vejamos:

Não foi fornecido texto alternativo para esta imagem

Construtor Parametrizado

O interessante é que em Dart você pode fazer melhor, vejamos:

Não foi fornecido texto alternativo para esta imagem

Como já instanciamos o construtor, podemos fazer da seguinte forma:

Não foi fornecido texto alternativo para esta imagem

Named Constructors (Construtor Nomeado)

É outro tipo de construtor, é um construtor diferenciado para quando se tem parâmetros diferentes, seria um construtor que tem um nome:

Não foi fornecido texto alternativo para esta imagem

Para poder chamar este named constructors eu faço o seguinte em "void main();":

Não foi fornecido texto alternativo para esta imagem

No caso acima irá mostrar no nosso console as seguintes mensagens:

Pedro nasceu!
Pedro está dormindo! 
0

Getters e Setters

Muitas das vezes nós não queremos que alguns atributos dos nossos objetos ou classes não sejam acessíveis externamente, por questões de segurança.

Assim, basta colocar um "_" à frente do atributo que quer privar, ou seja, ele só poderá ser acessado de dentro da classe ou objeto:

String _idade;

Então, para poder acessar estes atributos, utilizamos os Getters. Para declarar um Getter basta:

Não foi fornecido texto alternativo para esta imagem

Assim, será possível acessar o atributo _idade usando a variável idade. Porém, com o Getter só podemos saber qual a idade, mas não podemos mudar tal atributo. Para isso, alterar o atributo, utilizamos um Setter:

Não foi fornecido texto alternativo para esta imagem

 Herança

Herança é um dos pontos chave de programação orientada a objetos (POO). A ideia de herança é facilitar a programação. Uma classe A deve herdar de uma classe B quando podemos dizer que A é um B. Lembre-se que em Dart, tudo é um objeto. Vamos declarar duas classes, uma chamada cachorro e a outra gato, vamos atribuir duas variáveis aos dois: nome e peso:

Não foi fornecido texto alternativo para esta imagem

Agora, vamos atribuir alguns métodos aos dois como "comer" e "fazer som". Vamos diferenciar também a variável "fofura" para o cachorro e "está amigável" para o gato:

Não foi fornecido texto alternativo para esta imagem

Perceba que em ambas as classes há atributos semelhantes. Aqui que entra a herança, vamos criar uma classe "Animal" com os atributos semelhantes entre o Gato e Cachorro e extender a classe Animal a ambos, ou seja, eles herdam as propriedades de da classe "Animal", tudo que o animal tem, cachorro e gato também tem:

Não foi fornecido texto alternativo para esta imagem

Vamos agora criar alguns construtores:

Não foi fornecido texto alternativo para esta imagem

Repare nos comentários dos códigos que nós criamos que colocamos alguns construtores, portanto iremos criar nossos animais na classe mãe:

Não foi fornecido texto alternativo para esta imagem

Reescritura de Métodos e Modificadores Static, Final e Const

Quando se tem um método, como por exemplo o método de "fazer som" da classe "Animal" do artigo anterior, e eu quero que este método se comporte diferente ou altere o conteúdo dele dentro das outras classes "cachorro" ou "gato".

Não foi fornecido texto alternativo para esta imagem

Para fazer isso é simples, basta colocar o "@override" e colocar o método exatamente como está na outra classe. E ao executar o método ele não irá pegar o método da classe "Animal", mas sim da classe que eu adicionou o termo acima, vejamos:

Não foi fornecido texto alternativo para esta imagem

Toda classe no Dart estende, mesmo que não especifique, uma classe chamada "object" que é uma classe de objeto do Dart. Essa classe tem um método chamado "toString" que também podemos reescrever:

Não foi fornecido texto alternativo para esta imagem

Se colocarmos agora print(cachorro); ele trará a reescrita que fizemos, porém só para cachorro.

class Valores { 

}

Essa é uma classe em que eu quero armazenar algumas constantes do código, não irei instanciar objetos nela, só irei criá-la para organizar minhas constantes.

class Valores {
  int vezesClicado;
}

Para eu acessar a variável "vezesClicado" da classe "Valores" sem ter que instanciá-la, eu acrescento o modificador "static" à variável, tornando a variável não mais do objeto, mas sim da classe. E assim podemos utilizar o nome da classe + o nome da variável, vejamos:

class Valores {
  static int vezesClicado;
}

void main(){
  Valores.vezesClicado = 2;
}

Outro modificador que temos é o "const" que a partir do momento que você define uma variável como "const", ela não pode ser alterada em nenhum momento, ela também é uma constante em tempo de compilamento, ou seja, em qualquer lugar que eu a colocar ela será substituída pelo valor que foi definido.

E por último temos o "final" que funciona assim, vamos supor que eu tenha uma classe "Pessoa" e eu queira declarar que uma variável (objeto) "pessoa" é igual ao objeto "Pessoa", mas não quero que esta "pessoa" seja alterada em nenhum momento, ou seja, sempre será a mesma. Então, é para isso que se usa o "final" e como a "const" ela também é em tempo de execução, assim, não se pode pegar "pessoa" e colocar outro objeto nela, vejamos como ficaria:

class Pessoa { 

} 

void main(){
  final Pessoa pessoa = Pessoa();
  // não se pode mais fazer: pessoa = Pesso();
}

Classes Abstratas

O problema da Herança Multipla

Em Dart não se pode fazer uma herança multipla, ou seja, uma classe não pode herdar de duas classes. Mas você sabe o por quê? A herança múltipla possui o problema de conflito de nomes. Imagine se você criar uma classe chamada Humano que tenha um atributo nome, e uma Classe Robô que também tenha o atributo nome. Ao criar uma classe Android que herde de Humano e de Robô você vai ter problemas sérios, geralmente complicados de resolver. Herança Múltipla é uma das facilidades que geralmente não facilitam nada que criamos.Então para resolver este problema nós utilizamos a interface ou abstract class, no caso exposto acima, Android será uma classe abstrata.

Objetivo

O objetivo aqui é pegar classes não relacionadas, isto é, pegar funcionalidades comuns para classes não relacionadas.Assim, por exemplo, um gato, cachorro, leão podem ser agressivos, mas esta relação é diferente de uma relação de herança, é uma relação de implementação (implementam aquilo que existe na classe Agressivos).Portanto não estamos limitados somente a heranças, mas também podemos usar interfaces ou classes abstratas. Isto tudo se resume a seguinte pergunta: como podemos utilizar funções comuns para classes não relacionadas? é para quebrar esse limite que temos uma classe que não pode jamais herdar de duas classes. O gato, cachorro e leão continuam sendo Animais, herdam esta característica, porém a agressão é uma implementação.

Classes Abstratas

Não é concreta, é só uma idéia, um conceito abstrato, uma classe genérica só tem um conteúdo padrão que depois poderá ser implementado de uma forma concreta. Ex. se eu disser que gosto de formas (é muito genérico), a pergunta que você faria seria qual forma? aí vem a classe concreta que explica que tipo de forma. Por exemplo, dentro de Animal temos os felinos e pessoas, dentro de felinos gato e tigre que são concretos. Assim, vemos que as classes abstratas são genéricas. Usamos a palavra chave abstract para impedir que uma classe possa ser instanciada. Esse é o efeito direto de se usar o modificador abstract na declaração de uma classe:

Não foi fornecido texto alternativo para esta imagem

Para usá-la, basta colocar abstract antes da classe que quer tornar abstrata, assim, não poderá instanciá-la, mas poderá usá-la como super classe para herdar algo. Pode-se também declarar métodos nas classes abstratas sem declarar nada, sem nenhum corpo, ou seja, na parte void fazerSom() pode-se retirar o seu corpo, desta forma:

Não foi fornecido texto alternativo para esta imagem

Porém, será obrigado a implementar (com implements ou extends) ela nas classes que herdam a classe abstrata. E sempre que implementá-las temos que implementar o método:

Não foi fornecido texto alternativo para esta imagem

Agora vamos em declarar em main para ver o que ocorre:

Não foi fornecido texto alternativo para esta imagem

Irá mostrar 'Garfield comeu' no console, veja que implementamos o método comer da classe abstrata no Gato. 

Qual o potencial dessa classe?

Vamos criar tudo novamente, primeiro uma classe Animal:

Não foi fornecido texto alternativo para esta imagem

Perceba que só fizemos um "contrato" não especificamos nada na classe abstrata Animal, pois iremos implementá-la em outra classe, portanto vamos criar a classe Pessoa e implementar esse contrato que dizemos:

Não foi fornecido texto alternativo para esta imagem

A partir do momento que a implemento, o Dart já exige que declaremos o estas classes. Vamos fazer o teste e ver o que acontece:

Não foi fornecido texto alternativo para esta imagem

Debug:

Tiago respirando igual um humano
Tiago fazendo som como Humano e é Brasileiro

Viu que interessante. Geralmente a utilizamos para sabermos o que queremos implementar.

Vamos nos aprofundar um pouco mais criando a classe abstrata Engracado e criar um modelo de contrato, fazerRir();:

Não foi fornecido texto alternativo para esta imagem

Criaremos uma classe Humorista que extenderá Pessoa implementando a classe Engracada:

Não foi fornecido texto alternativo para esta imagem

testando:

Não foi fornecido texto alternativo para esta imagem

debug:

Pedro fazendo som como Humano e é Americano


Pedro respirando igual um humano


Pedro é um humorista engracado

Legal né? Assim, você pode ir implementando uma na outra, podemos fazer, por exemplo, outra classe chamada Palestra que não tem relação com Animal, nem é uma pessoa, mas que pode implementar a classe Engracado. 

Pra que server esse trem?

Bom, no código escrito acima, não faz sentido criar o objeto "Animal", pois eu só quero saber que tipo de animal é, entendeu? O que, exatamente, vem a ser a nossa classe Animal? Eu só tenho dois animais gato e cachorro. Ela é uma classe que apenas idealiza um tipo, define apenas um rascunho, um contrato. Para o nosso sistema, é inadmissível que um objeto seja apenas do tipo Animal (pode existir um sistema em que faça sentido ter objetos do tipo Animal, mas no nosso caso não).

Mixin

Mixin é uma classe abstrata como qualquer outra, mas a grande ideia a respeito dele é que não é permitido ter heranças múltiplas em Dart, para isso Dart contornou a situação e criou uma saída Mixin é uma classe abstrata como qualquer outra, mas a grande ideia a respeito dele é que não é permitido ter heranças múltiplas em Dart, então Dart conseguiu contornar este problema utilizando a estrutura chamada Mixin. Para poder entender vamos codar, criando algumas classes abstratas:

Não foi fornecido texto alternativo para esta imagem

Agora, criaremos uma classe chamada Dançar, porém ela será um Mixin:

Não foi fornecido texto alternativo para esta imagem

O bom é que você pode obrigar a sua classe mixin só seja utilizada em uma classe específica, como posta acima, basta colocar on NomeDaClasse. Assim, só quem poderá utilizar este mixin é quem extender a classe Artista.

Não foi fornecido texto alternativo para esta imagem

Para dizer que Diego canta e dançar, basta adicionar o termo with e adicionar as demaisa classes:

Não foi fornecido texto alternativo para esta imagem

Caso você queira acrescentar mais classes, você pode utilizar uma vírgula e acrescentar a nova classe posteriormente:

Não foi fornecido texto alternativo para esta imagem


OBS. Dart observa a hierarquia de implementação, no caso apresentado acima, foi implementado primeiro Cantar e depois Dançar, desta forma ele implementa as classes nesta ordem.

Para usar basta instanciar a classe criada e chamar os atributos criados:

Não foi fornecido texto alternativo para esta imagem

Como encadear as requisições, ou seja, diminuir o código acima? basta colocar .. 

Não foi fornecido texto alternativo para esta imagem

Bom pessoal, esse é o conteúdo de POO para Dart. Utilizei como referencia alguns artigos encontrados na internet em conjunto com vídeo-aulas que usei durante o meu aprendizado.


Ryan Estácio

Desenvolvedor Mobile, Flutter.

4 m

Ótimo artigo, parabéns e obrigado.

Helson Gonçalves

Sistemas | Administração | BackOffice |

3 a

Parabéns Gabriela Pereira dos Santos, material Riquíssimo e de fácil entendimento irei utilizar bastante !!! Obrigado

Ana Luísa Dias

Desenvolvedor Java | SQL | Azure DevOps | Backend Developer

4 a

Vou guardar esse artigo com carinho! Obrigada <3

Entre para ver ou adicionar um comentário

Outros artigos de Gabriela Pereira dos Santos

  • Com licença senhor. Tem um minuto para ouvir a palavra do Flutter ? - Web, Desktop, Null Safety e muito mais!

    Com licença senhor. Tem um minuto para ouvir a palavra do Flutter ? - Web, Desktop, Null Safety e muito mais!

    Hoje aconteceu o Flutter Engage, o evento focado em anunciar as novidades do Flutter e Dart. E para celebrar a minha…

    7 comentários
  • CI/CD

    CI/CD

    Integração contínua (CI) e Entrega contínua (CD) são essencialmente dois processos diferentes que trabalham com o mesmo…

  • Amazon EC2

    Amazon EC2

    Para entender o valor do EC2, você precisa entender o que existia antes de este serviço existir. No passado, as…

  • Provider - Flutter

    Provider - Flutter

    O Flutter é uma estrutura declarativa. Isto é, diferente do framework imperativo, o Flutter não permite a alteração do…

  • Persistência de dados com Flutter

    Persistência de dados com Flutter

    Dados persistentes são muito importantes para os usuários, pois seria inconveniente para eles digitarem suas…

    7 comentários
  • E essa é a parte da minha vida, que chamo de felicidade.

    E essa é a parte da minha vida, que chamo de felicidade.

    Um filme muito bacana para aprender boas lições de vida é À Procura da felicidade, com Will Smith, o filme foi lançado…

  • Projetos ágeis com SCRUM

    Projetos ágeis com SCRUM

    Todo mundo que já trabalhou com engenheiros de software ou na indústria de tecnologia já ouviu as palavras “Agile” e…

  • Testes automatizados com Flutter & Dart

    Testes automatizados com Flutter & Dart

    Para começar a falar sobre testes, precisamos entender os tipos e quando utiliza-los. Para isso, devemos iniciar nosso…

    8 comentários
  • Um estudo sobre Dart, a linguagem do Google

    Um estudo sobre Dart, a linguagem do Google

    Se você começou a estudar um pouco sobre o Flutter, provavelmente deve ter trabalhado um pouco com o Dart… Se você…

  • The Social Dilemma

    The Social Dilemma

    “Quando algo online é gratuito, você não é o cliente; você é o produto. ” Como humanos, estamos programados para nos…

    1 comentário

Outras pessoas também visualizaram

Conferir tópicos