Open jemluz opened 8 months ago
Se alguns desses atributos ou métodos forem facilmente visíveis e modificáveis, como o mecanismo de aceleração do carro, isso pode dar liberdade para que alterações sejam feitas, resultando em efeitos colaterais imprevisíveis. Nessa analogia, uma pessoa pode não estar satisfeita com a aceleração do carro e modifica a forma como ela ocorre, criando efeitos colaterais que podem fazer o carro nem andar, por exemplo.
Como sabemos como o nosso carro acelera? É simples: não sabemos. Nós só sabemos que para acelerar, devemos pisar no acelerador e de resto o objeto sabe como executar essa ação sem expor como o faz. Dizemos que a aceleração do carro está encapsulada, pois sabemos o que ele vai fazer ao executarmos esse método, mas não sabemos como - e na verdade, não importa para o programa como o objeto o faz, só que ele o faça.
Não sabemos como o carro sabe qual velocidade mostrar no velocímetro ou como ele calcula sua velocidade, mas não precisamos saber como isso é feito. Só precisamos saber que ele vai nos dar a velocidade certa. Ler ou alterar um atributo encapsulado pode ser feito a partir de getters e setters (colocar referência).
Exemplo de encapsulamento aplicado a uma classe Carro, em java:
public class Carro {
private Double velocidade;
private String modelo;
private MecanismoAceleracao mecanismoAceleracao;
private String cor;
/* Repare que o mecanismo de aceleração é inserido no carro ao ser construído, e
não o vemos nem podemos modificá-lo, isto é, não tem getter nem setter.
Já o "modelo" pode ser visto, mas não alterado. */
public Carro(String modelo, MecanismoAceleracao mecanismoAceleracao) {
this.modelo = modelo;
this.mecanismoAceleracao = mecanismoAceleracao;
this.velocidade = 0;
}
public void acelerar() {
this.mecanismoAceleracao.acelerar();
}
public void frear() {
/* código do carro para frear */
}
public void acenderFarol() {
/* código do carro para acender o farol */
}
public Double getVelocidade() {
return this.velocidade
}
private void setVelocidade() {
/* código para alterar a velocidade do carro */
/* Como só o próprio carro deve calcular a velocidade,
esse método não pode ser chamado de fora, por isso é "private" */
}
public String getModelo() {
return this.modelo;
}
public String getCor() {
return this.cor;
}
/* podemos mudar a cor do carro quando quisermos */
public void setCor(String cor) {
this.cor = cor;
}
}
Exemplo de encapsulamento aplicado a uma classe Carro, em python:
class Carro:
def __init__(self, modelo, mecanismoAceleracao):
self.__modelo = modelo;
self.__velocidade = 0
self.__mecanismoAceleracao = mecanismoAceleracao
def acelerar(self):
mecanismoAceleracao.acelerar()
def frear(self):
# Codigo para frear o carro
def acenderFarol(self):
# Codigo para acender o farol do carro
def getVelocidade(self):
return self.velocidade
def __setVelocidade(self):
# Codigo para alterar a velocidade por dentro do objeto
def getModelo(self):
return self.modelo
def getCor(self):
return self.cor
def setCor(self, cor):
self.cor = cor
estatic
Quando utilizamos a palavra static em um método de uma classe, permitimos que esse método seja chamado sem precisar criar uma instancia da classe.
Por isso sempre que rodamos a função main para executar nosso programa, tomamos o cuidado de declarar ela como static
, do contrário precisariamos instanciar a classe do programa antes.
Se usado em variáveis, é como se fixasse o valor. Se você não coloca static nas variáveis, elas ficam com uma cópia diferente pra cada objeto (o que é o mais usual).
Blocos de inicialização são bloquinhos com coisas que você quer que executem quando a classe for carregada na virtual machine, o que acontece apenas uma vez (é bem pouco usado, é mais só pra saber que existe).
Por exemplo:
static {
System.out.println("O classloader carregou essa classe!!");
}
E classes internas são classes dentro de classes, que também podem ser static (também pouco usado, mas saiba que existe). Por exemplo:
class Externa {
static class Interna {
}
}
Encapsulamento
Quando criamos uma classe, dentro dela haverá a declaração dos atributos e métodos necessários para nutrir e manipular os objetos que serão criados a partir dessa classe.
No entanto, se alguns desses atributos ou métodos forem facilmente visíveis e modificáveis, isso pode dar liberdade para que alterações sejam feitas, resultando em efeitos colaterais imprevisíveis.
Rótulos
public
andprivate
Na POO, um atributo ou método que não é visível de fora do próprio objeto é chamado de "privado" e quando é visível, é chamado de "público".
Quando um atributo/método for definido como privado, dizemos que ele está encapsulado.
Esse encapsulamento de atributos e métodos impede o chamado vazamento de escopo, onde um atributo ou método é visível por alguém que não deveria vê-lo, como outro objeto ou classe.
Isso evita a confusão do uso de variáveis globais [citada na issue anterior] no programa, deixando mais fácil de identificar em qual estado cada variável vai estar a cada momento do programa, já que a restrição de acesso nos permite identificar quem consegue modificá-la.
Getters
São métodos focados em fornecer o valor de um atributo privado. Você não mais consultará o atributo diretamente, até por quê o rotulo de private impedirá, ao invés disso tu chama um get (que terá rótulo público) e ele sim irá consultar a propriedade para você.
Como um cliente que chama um garçon para perguntar a ele se na cozinha tem algum ingrediente especifico. O cliente não irá levantar e verificar por ele mesmo.
Setters
São métodos focados em alterar o valor de um atributo privado. Você não mais consultará o atributo diretamente, até por quê o rotulo de private impedirá, ao invés disso tu chama um set (que terá rótulo público) passando para esse método o novo valor desejado ele irá realizar a operação de definir esse novo valor.
Como quem chama o garçon para fazer uma alteração no pedido que já foi solicitado. O cliente não irá levantar e fazer isso por ele mesmo.
Exemplo
Criamos uma classe de conta bancaria, com 2 métodos, depositar e sacar.
Nesse caso eu tenho a liberdade para alterar as propriedades de um obj da classe diretamente.
Abaixo encapsularemos a classe conta, adicionando os rótulos private e public aos seus atributos e métodos. Além também de adicionar os Getters e Setters.
Após o encapsulamento todo o acesso e manipulação de um objeto da classe é feito através de getters e setters.
Exemplos baseados no artigo: Encapsulamento, herança e polimorfismo: as principais características da POO