sábado, 6 de março de 2010

Dialogo sobre Encapsulamento


Televisao: Eu sou um objeto da classe Televisao, conforme descrito abaixo, e tenho alguns atributos e metodos que sao essenciais para voce poder assistir os seus programas preferidos.

public class Televisao {
   private boolean ligado;
   private float canal;
   private int volume;

   //getters e setters da Televisao
}

ControleRemoto: Eu sou um objeto da classe ControleRemoto e recebi voce (objeto Televisao) quando fui instanciado. Agora me fale como eu faco para usa-lo porque hoje a noite tem um jogao de futebol que nao posso perder...

public class ControleRemoto
 {
   // variavel de instancia do tipo Televisao
   Televisao tv;

   // construtor que recebe um objeto Televisao
   // e atribui a variavel de instancia
   public ControleRemoto(Televisao tv) {
      this.tv = tv;
   }

   //coloque aqui os metodos do controle remoto
}


Televisao: Para voce assistir o jogo de futebol eh necessario mudar o estado dos meus ATRIBUTOS: ligado, canal e volume.

ControleRemoto: Assim ta facil... eh so implementar os meus metodos usando a variavel de referencia "tv" para acessar diretamente seus atributos e alterar os valores que eu preciso.


   // metodos do controle remoto
   public void ligaTV() {
      tv.ligado = true;
   }

   public void desligaTV() {
      tv.ligado = false;
   }

   public void aumentaVolume() {
      tv.volume++;
   }

   public void diminuiVolume() {
      tv.volume--;
   }

   public void mudaCanal(float canal) {
      tv.canal = canal;
   }


Televisao: Na verdade voce nao consegue fazer isso... porque o programador que criou a minha classe usou o principio do encapsulamento.

ControleRemoto: Encapsu o que??? Agora voce complicou tudo com esse palavrao...

Televisao: Para entender melhor o conceito de encapsulamento, vamos tentar entender a problematica por traz disso... imagine que voce consiga acessar diretamente o meu atributo canal... eu tenho certeza que voce iria querer colocar o numero do canal da sua emissora favorita no atributo canal, certo?

ControleRemoto: Eh exatamente isso que eu ia fazer... apesar de ter percebido que o atributo canal eh do tipo float... Por que voce usa no atributo canal o tipo float e nao um int?

Televisao: Na verdade eu uso um valor de oscilacao de radio-frequencia que eh a medida em hertz para que eu possa sintonizar o canal...

ControleRemoto: Xiii, ja vi tudo... eu teria que me tornar um especialista em eletronica para poder alterar o valor do atributo canal, certo?

Televisao: Isso mesmo... a ideia do encapsulamento eh que voce NAO precisar saber os detalhes do meu funcionamento... pois os meus metodos publicos encapsulam a complexidade que eu tenho que tratar internamente...

   // getters e setters da Televisao
   public boolean getLigado() {
      return this.ligado;
   }

   public void setLigado(boolean ligado) {
      this.ligado = ligado;
   }

   // o metodo get pega o valor do atributo canal em Hz
   // e converte para o numero do canal que conhecemos
   public int getCanal() {
      // imaginem um calculo muito complexo que eh atribuido
      // para a variavel local canalTipoInteiro
      return canalTipoInteiro;
   }

   // o metodo set pega o numero do canal que conhecemos
   // e converte para o valor do atributo canal em Hz
   public void setCanal(int canal) {
      // imaginem o mesmo calculo complexo que eh atribuido
      // para a variavel local canalTipoFloat
      this.canal = canalTipoFloat;
   }

   public int getVolume() {
      return this.volume;
   }

   public void setVolume(int volume) {
      // nao eh permitido valor negativo
      // valor superior a 30 podem estourar os falantes da tv
      if (volume >= 0 & volume <= 30){
         this.volume = volume;
      }
   }


ControleRemoto: ufa, ainda bem... senao eu teria que fazer um curso de eletronica para poder selecionar o canal do jogo do campeonato brasileiro que vai passar hoje a noite...

Televisao: Todos os objetos que venham a me usar nao tem a obrigacao de saber essas coisas complexas e chatas de faixas de frequencia para captar o sinal de transmissao do canal, e por isso meus metodos possuem uma interface mais amigavel para que outros objetos como voce possam me usar com facilidade.

ControleRemoto: Entao eu tenho que implementar as minhas chamadas a voce chamando os seus metodos do jeito que esta abaixo:

   // metodos do controle remoto

   public void ligaTV() {
      tv.setLigado(true);
   }

   public void desligaTV() {
      tv.setligado(false);
   }

   public void aumentaVolume() {
      int volumeAtual = tv.getVolume();
      tv.setVolume(volumeAtual++);
   }

   public void diminueVolume() {
      int volumeAtual = tv.getVolume();
      tv.setVolume(volumeAtual--);
   }

   public void mudaCanal(int canal) {
      tv.setCanal(canal);
   }


Televisao: Isso mesmo!!! O segredo do encapsulamento eh que eu faco um montao de coisas que voce nem mesmo fica sabendo... Ja pensou se voce tivesse que calcular o valor correto da frequencia e atribuir diretamente o valor ao atributo canal?

ControleRemoto: Putz, eh mesmo... se eu calculasse errado o valor, poderia sintonizar a novela, ao inves do jogo do campeonato brasileiro...

Televisao: Por isso, meus atributos sao private e voce somente pode acessa-lo atraves dos meus metodos publicos, assim voce nao faz besteiras e tudo funciona bem!

ControleRemoto: Agora entendi o beneficio do encapsulamento...