Instanciação e referência (fundamentos)

Boa noite gente

Guys, estou ainda com um nó na minha cabeça e gostaria que me ajudasse a desenrolar este nó. Assim, quando eu possuo uma esta instanciação:

Funcionario sandro = new Diretor();

eu poderia dizer o que o funcionário “sandro” esta apontando pra duas referências? Se “sim”, eu não conseguiria usar os atributos da classe diretor??

Em quais casos eu devo utilizar esta abordagem ??

muito obrigado

Trata-se apenas de uma referência. Mesmo sendo classes diferentes, a relação de herança trata ambas como uma só instância.

Consegue se vc definir as propriedades da classe Diretor como protected. Assim, vc conseguiria acessar essas propriedades diretamente pela classe filha (Funcionario).

Lucas, eu acho que quando ele perguntou sobre acessar atributos, ele quis dizer algo assim:

public class App {
  public static void main(String... args) {
    class Funcionario {
      int umAtributoQualquer = 123;
    }

    class Diretor extends Funcionario {
      int umAtributoQueSoDiretorTem = 456;
    }

    Funcionario sandro = new Diretor();
    System.out.println(sandro.umAtributoQueSoDiretorTem);
  }
}

Se for isso mesmo do caso acima, vc não vai conseguir, pois dá erro de compilação.

Para acessar membro da subclasse, vc teria que fazer um casting:

System.out.println( ((Diretor) sandro).umAtributoQueSoDiretorTem );

Eu imagino que isso pareça estranho para vc, afinal “está óbvio que sandro é um Diretor, então como o compilador não consegue ver isso???”.

O ponto é que seu exemplo é simples demais e para fazer mais sentido vc precisa imaginar situações mais complexas.

Imagine que vc tem um programa grandinho, dividido em vários pacotes e num pacote vc tem isto:

package escola;

abstract class Funcionario {
  abstract void pagar();
}

class Escola {
  void pagarFuncionarios(Funcionario[] funcionarios) {
    for(int i = 0; i < funcionarios.length; i++) {
      funcionarios[i].pagar();
    }
  }
}

A classe Escola não tem como saber se o array funcionarios contém algum Diretor, ou Professor ou Faxineiro. Na verdade, para ela nada importa isso, só o que importa é que sejam Funcionario e assim implementem o método pagar().

Como uma linguagem de tipagem forte, o Java se importa muito com os tipos e exige que vc seja bem explícito quando quiser fazer a conversão de um tipo para outro compatível, é o caso do uso do cast, em código ele fica feio já pra ficar bem destacado a intenção do programador.

Agora imagine como seria ruim se vc tivesse um método pagarFuncionarios() para cada tipo de funcionário que tem na sua escola!

class Escola {
  void pagarDiretor(Diretor[] diretores) {
    for(int i = 0; i < diretores.length; i++) {
      diretores[i].pagar();
    }
  }

  void pagarProfessor(Professor[] professores) {
    for(int i = 0; i < professores.length; i++) {
      professores[i].pagar();
    }
  }

  void pagarFaxineiro(Faxineiro[] faxineiros) {
    for(int i = 0; i < faxineiros.length; i++) {
      faxineiros[i].pagar();
    }
  }
}

Não faria sentido ter todo este trabalho se todos possuem o método pagar(). Neste caso, ter Funcionario como superclasse ajuda bastante.

Estes são exemplos bobos, as coisas ficarão mais claras conforme vc aprender mais e botar em prática numa aplicação real.

Sobre sua dúvida a respeito das 2 referências, complementando o que o Lucas disse, vc tem que pensar que, para todos os efeitos, Diretor é um Funcionario.

4 curtidas

Muito obrigado pela excelente explicação !!! agregou bastante no meu conhecimento.

1 curtida