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".
// 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;
}
}
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.
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;
}
}
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");
}
}
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.
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étodosgetters
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());
}
}
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.
- Quando criamos um objeto (instância) de classe, o espaço é reservado na memória
heap
. - 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
- A variável de referência é usada para apontar objetos/valores.
- 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.
- 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.
- Você pode acessar os membros do objeto usando uma variável de referência usando a sintaxe de ponto.
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:
- Cada donzela no salão é uma instância de objeto.
- Um cavalheiro sem uma donzela poderá escolher partir.
- É super natural a mudança entre os pares
referência
eobjeto
. - Os objetos serão acessados somente através da sua referência.
- Não é muito comum mas possível um objeto ser referenciado por duas ou mais variáveis.
- Duas donzelas gêmeas ou de nomes iguais ainda assim são objetos diferentes.
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