Orientacao Objetos

Classes e Objetos

Classes vs Objetos

Para compreendermos exatamente do que se trata a orientação a objetos, vamos entender quais são os requerimentos de uma linguagem para ser considerada nesse paradigma. Para isso, a linguagem precisa atender sobre o conceito de classes e os quatro pilares da orientação a objetos.

Primeiramente, devemos compreender que o conceito orientado a objetos, recomenda que toda estrutura de nosso código baseada a objeto seja um Identificador, Características e Comportamentos.

Toda a estrutura de código na linguagem Java é distribuído em arquivos com extensão .java denominados de classe.

As classes existentes em nosso projeto, serão composta por:

Identificador, Características e Comportamentos.

  • Classe (class): A estrutura e/ou representação que direciona a criação dos objetos de mesmo tipo.
  • Identificador (identity): Propósito existencial aos objetos que serão criados.
  • Características (states): Também conhecido como atributos ou propriedades, é toda informação que representa o estado do objeto.
  • Comportamentos (behavior): Também conhecido como ações ou métodos, é toda parte comportamental que um objeto dispõe.
  • Instanciar (new): É o ato de criar um objeto a partir de estrutura, definida em uma classe.

Estrutura

Para ilustrar as etapas de desenvolvimento orientada a objetos em Java, iremos reproduzir a imagem abaixo em forma de código para explicar que primeiro criamos a estrutura correspondente, para assim criá-los com as características e a possibilidade de realização de ações (comportamentos), como se fosse no "mundo real".

Ilustração de uma classe Estudante e 03 Objetos criados

// Criando a classe Student
// Com todas as características e compartamentos aplicados
public class Student {
    String name;
    int age;
    Color color;
    Sex sex;

    void eating(Lunch lunch){
      //NOSSO CÓDIGO AQUI
    }
    void drinking(Juice juice){
      //NOSSO CÓDIGO AQUI
    }
    void running(){
      //NOSSO CÓDIGO AQUI
    }
}

Instâncias

Uma instância é ação de criar um objeto. Quando dizemos que John pertence a classe Student, podemos dizer que John é uma instância da classe Student, da mesma forma, Sophia e Lily também são instâncias da classe Student.

// Criando objetos a partir da classe Student
public class School {
    public static void main(String[] args) throws Exception {
      Student student1 = new Student(); 
      student1.name= "John";
      student1.age= 12;
      student1.color= Color.FAIR;
      student1.sex= Sex.MALE;

      Student student2 = new Student();
      student2.name= "Sophia";
      student2.age= 10;
      student2.color= Color.FAIR;
      student2.sex= Sex.FEMALE;

      Student student3 = new Student();
      student3.name= "Lily";
      student3.age= 11;
      student3.color= Color.DARK;
      student3.sex= Sex.FEMALE;
    }
}
🔔 Atenção
No exemplo acima, NÃO estruturamos a classe Student com o padrão Java Beans getters e setters.

Seguindo algumas convenções, as nossas classes são classificadas como:

  • Classe de modelo (model): classes que representam estrutura de domínio da aplicação, exemplo: Cliente, Pedido, Nota Fiscal e etc.
  • Classe de serviço (service): classes que contém regras de negócio e validação de nosso sistema.
  • Classe de repositório (repository): classes que contém uma integração com banco de dados.
  • Classe de controle (controller): classes que possuem a finalidade de disponibilizar alguma comunicação externa, à nossa aplicação, como http web ou webservices.
  • Classe utilitária (util): classe que contém recursos comuns, à toda nossa aplicação.

🏆 Sucesso
Exercite a distribuição de classes, por papéis dentro da sua aplicação, para que se possa determinar a estrutura mais conveniente, em cada arquivo do seu projeto.

Construtores

Instância e Construtores

Aprendemos que as classes são definições estruturais e comportamentais dos objetos que existirão de suas diretrizes, exemplo:

Quando criamos um objeto a partir das definições de uma respectiva denominamos que estamos construindo este objeto através do recurso de construtor padrão na linguagem Java.

Vamos imaginar que tem a classe Pessoa onde a mesma determina que cada objeto criado terá as características: Nome, Data Nascimento, Endereço e Telefone:

Definindo a classe Pessoa:

import java.util.Date;

public class Pessoa {
    String nome;
    Date dataNascimento;
    String endereco;
    Long telefone;
}

Criando três pessoas com o que denominamos de construtor padrão:

public class ConstrutorPessoa {
    public static void main(String[] args) {
        Pessoa carlos   = new Pessoa();
        Pessoa lucas    = new Pessoa();
        Pessoa diego    = new Pessoa();
        
        //Existem 3 pessoas no sistema sem nenhuma característica
    }
}

Agora, iremos dizer que nosso contrato (classe) que para uma pessoa existir o nome deverá ser obrigatório no ato da construção deste objeto.

public class Pessoa {
    String nome;
    Date dataNascimento;
    String endereco;
    Long telefone;
    
    // se o nome do parâmetro for igual, use a palavra reservada this
    // this.nome = nome
    Pessoa (String novoNome){
        nome = novoNome;
    }
}
🔔 Atenção
A classe ConstrutorPessoa passará a apresentar um erro na tentativa de criar os objetos, vamos corrigir conforme abaixo:
public class ConstrutorPessoa {
    public static void main(String[] args) {
        Pessoa carlos   = new Pessoa("carlos henrique");
        Pessoa lucas    = new Pessoa("lucas silva");
        Pessoa diego    = new Pessoa("diego felipe");
    }
}
🚨 Cuidado
Não use o recurso de construtores em excesso como forma de abreviar o algoritmo para criação e definições de seus objetos.

Enums

Enum, é um tipo especial de classe, onde os objetos são previamente criados, imutáveis e disponíveis por toda aplicação.

Usamos Enum quando o nosso modelo de negócio contém objetos de mesmo contexto, que já existem de forma pré-estabelecida com a certeza de não haver tanta alteração de valores.

Exemplos:

Grau de Escolaridade: Analfabeto, Fundamental, Médio, Superior;

Estado Civil: Solteiro, Casado, Divorciado, Viúvo;

Estados Brasileiros: São Paulo, Rio de Janeiro, Piauí, Maranhão.

🔔 Atenção
Não confunda uma lista de constantes com enum.

Enquanto que uma constante é uma variável de tipo com valor imutável, enum é um conjunto de objetos pre-definidos na aplicação.

Como um enum é um conjunto de objetos, logo, estes objetos podem conter atributos e métodos. Veja o exemplo de um enum para disponibilizar os quatro estados brasileiros citados acima, contendo informações de: Nome, Sigla e um método que pega o nome do de cada estado e já retorna para todo maiúsculo.

// Criando o enum EstadoBrasileiro para ser usado em toda a aplicação.
public enum EstadoBrasileiro {
    SAO_PAULO ("SP","São Paulo"),
    RIO_JANEIRO ("RJ", "Rio de Janeiro"),
    PIAUI ("PI", "Piauí"),
    MARANHAO ("MA","Maranhão") ;
    
    private String nome;
    private String sigla;
    
    private EstadoBrasileiro(String sigla, String nome) {
        this.sigla = sigla;
        this.nome = nome;
    }
    public String getSigla() {
        return sigla;
    }
    public String getNome() {
        return nome;
    }
    public String getNomeMaiusculo() {
        return nome.toUpperCase();
    }
    
}

Boas práticas para criar objetos Enum

  • As opções (objetos), devem ser descritos em caixa alta separados por underline (_), ex.: OPCAO_UM, OPCAO_DOIS;
  • Após as opções, deve-se encerrar com ponto e vírgula ";" ;
  • Um enum é como uma classe, logo, poderá ter atributos e métodos tranquilamente;
  • Os valores dos atributos, devem já ser definidos após cada opção, dentro de parênteses como se fosse um new;
  • O construtor deve ser privado;
  • Não é comum um enum possuir o recurso setter(alteração de propriedade), somente os métodos getters correspondentes.

Agora NÃO precisaremos criar objetos que representam cada estado, toda vez que precisarmos destas informações, basta usar o enum acima e escolher a opção (objeto), pré-definido em qualquer parte do nosso sistema.

// qualquer classe do sistema poderá obter os objetos de EstadoBrasileiro
public class SistemaIbge {
    public static void main(String[] args) {
        //imprimindo os estados existentes no enum
        for(EstadoBrasileiro uf: EstadoBrasileiro.values() ) {
           System.out.println(uf.getSigla() + "-" + uf.getNomeMaiusculo());
        }
        
        //selecionando um estado a partir das opções disponíveis
        EstadoBrasileiro ufSelecionado = EstadoBrasileiro.PIAUI;
        
        System.out.println("O estado selecionado foi: " + ufSelecionado.getNome());
    }
}

values() e valueOf()

O método values() retorna um array [] contendo todos os elementos disponíveis, logo, é possível realizar uma iteração for-each e obter cada elemento, veja o exemplo anteriormente.

O método valueOf(String name) é o recurso que converte o valor literal (texto) em um elemento do enum, exemplo:

public class EnumApp {
        public static void main(String[] args) {
            EstadoBrasileiro estadoLocalizado = EstadoBrasileiro.valueOf("RIO_JANEIRO");
    
            // depois de obter o estado pelo seu identificador
            // conseguimos explorar todos os seus recursos
            System.out.println(estadoLocalizado.getNome());
            System.out.println(estadoLocalizado.getSigla());
            System.out.println(estadoLocalizado.getNomeMaiusculo());
        }
    }
🚨 Cuidado
Java é sensível quanto ao aspecto dos literais em maiúsculo e minúsculo, veja o cenário abaixo:
public class EnumApp {
        public static void main(String[] args) {
            //erro
            EstadoBrasileiro estadoLocalizado = EstadoBrasileiro.valueOf("RIO JANEIRO");
            //erro
            EstadoBrasileiro estadoLocalizado = EstadoBrasileiro.valueOf("rio_janeiro");
            // OK
            EstadoBrasileiro estadoLocalizado = EstadoBrasileiro.valueOf("RIO_JANEIRO");
        }
    }

Referência

Uma variável de referência é uma variável que aponta para um objeto de uma determinada classe, permitindo que você acesse o valor de um objeto. Um objeto é uma estrutura de dados composta que contém valores que você pode manipular. Uma variável de referência não armazena seus próprios valores. Em vez disso, quando você faz referência à variável de referência.

Antes de começarmos com a variável de referência, devemos saber sobre os seguintes fatos.

  1. Quando criamos um objeto (instância) de classe, o espaço é reservado na memória heap.
  2. Então, criamos um elemento apontador ou simplesmente chamado variável de referência que simplesmente aponta o objeto (o espaço criado em uma memória heap).

Compreendendo a variável de referência

  1. A variável de referência é usada para apontar objetos/valores.
  2. Classes, interfaces, arrays, enumerações e anotações são tipos de referência em Java. As variáveis de referência contêm os objetos/valores dos tipos de referência em Java.
  3. A variável de referência também pode armazenar valor nulo. Por padrão, se nenhum objeto for passado para uma variável de referência, ela armazenará um valor nulo.
  4. Você pode acessar os membros do objeto usando uma variável de referência usando a sintaxe de ponto.
📌 Para fixar
Que tal uma ilustração em um contexto no Século XX?

Vamos viajar no tempo para podermos compreender como as nossas variáveis (referências) e objetos interagem entre si nesta majestosa e encantadora jornada que é a programação orientada a objetos.

Definindo os papéis

  • Heap (Salão de festas): Espaço reservado para o armazenamento dos objetos
  • Objeto (Donzela): Ser que reside na memória heap da aplicação.
  • Referência (Cavalheiro): Variável que irá conduzir o objeto referenciado

Interação de objetos versus referência

Imaginamos que o salão de festas heap está aberto para receber seus participantes aonde cada donzela new Donzela() aguardará o convite para uma dança de um determinado cavalheiro referência.

Pontos complementares:

  1. Cada donzela no salão é uma instância de objeto.
  2. Um cavalheiro sem uma donzela poderá escolher partir.
  3. É super natural a mudança entre os pares referência e objeto.
  4. Os objetos serão acessados somente através da sua referência.
  5. Não é muito comum mas possível um objeto ser referenciado por duas ou mais variáveis.
  6. Duas donzelas gêmeas ou de nomes iguais ainda assim são objetos diferentes.
🔔 Atenção
Sabemos que este conteúdo é muito abstrato, mas este conceito é extramente relevante para termos uma compreensão de como JVM gerencia seu espaço em memória.Tire uns minutinhos para enriquecer seus conhecimentos na arte e na dança. Link