Solucionado (ver solução)
Solucionado
(ver solução)
10
respostas

Instanciar uma classe vinculando-a a uma variável de outro tipo

Ola, não entendi muito bem como funciona essa questão "AreaCalculavel a = new Retangulo(3,2)"

Porque associar Retangulo a AreaCalculavel?

Porque não algo do tipo: "Retangulo r = new Retangulo(3,2)"

10 respostas

Mauricio, boa tarde.

Entao, creio que vc esteja estudando heranca em Java. Quando trabalhamos com heranca sempre fazemos a pergunta "é um?", no seu exemplo "Retangulo é uma AreaCalculavel?". Se a resposta for sim vc pode utilizar AreaCalculavel a = new Retangulo();, caso contrario daria erro.

Exemplo:

class Pessoa { }

class Funcionario extends Pessoa { }

No exemplo acima, a classe funcionario extende (herda) Pessoa, logo podemos afirmar que Funcionario é uma Pessoa, entao seria correto ter: Pessoa p = new Funcionario();

Uma forma correta de se pensar é que a variavel "p" é do tipo "Pessoa" e recebe um novo objeto "Funcionario" (new Funcionario()) que tem tudo (herda da classe Pessoa) que uma classe "Pessoa" precisa.

Da mesma forma acontece com uma interface.

Espero ter esclarecido.

Existe um outro motivo para se fazer assim. Usando uma classe base, uma classe abstrata ou uma interface, permitimos uma maior flexibilidade de expansão do programa. 
Se daqui há algum tempo nos for solicitado estender a aplicação para receber outros tipos de objetos que herdem dessa classe base (ou superclasse), não teremos problemas pois o sistema trabalha com a interface de objetos e não com um tipo específico de objeto. 
Se declaramos uma variável com um tipo específico, ficamos amarrados a apenas um tipo objeto e não poderemos reutilizar o mesmo método.
Por exemplo, se no seu exercício acima você tiver que trocar de retângulo para círculo, triangulo ou hexágono, você não terá problema algum declarando a variável como do tipo AreaCalculavel. Mas imagine se você declarar como retângulo e precisar trabalhar com um hexágono. Você teria que criar outro método ou alterar o método atual, replicando código, para trabalhar com o novo tipo de objeto.
Essa é a vantagem de se trabalhar com uma interface e não diretamente com uma implementação, no caso um objeto específico.

Espero ter ajudado. Se tiver ainda alguma dúvida pode perguntar.
Obs.: dê uma olhada rápida em padrões de projeto, em algum livro ou revista, isso deve te ajudar a entender melhor.

abraço,
Sandro.

Blz gente. Confesso que ainda estou meio confuso... mas vou dar uma olhada em alguma literatura sobre porque se cria uma variável a associando a um tipo ou classe e tentar aplicar nesses comentários de vocês e ao exercício.

Tá faltando um "detalhezinho" pra eu pegar o "fio da meada"..rs Muito obrigado a todos

Eu nao sei se a minha explicacao esta 100% correta ou seria a resposta final, mas aqui esta o que eu entendi ate agora.

O por quê declarar uma referencia do tipo da interface?

Polimorfismo e o uso de interfaces. Pra ter as duas coisas você precisa fazer isso, esse é um motivo.

Marcio,

Não fique imaginando apenas o exercício em si. Pense que você foi contratado para desenvolver um sistema maior que emita notas fiscais para uma empresa em que sejam comercializados serviços e produtos, como uma concessionária de automóveis. Você leva seu carro até lá e eles executam um serviço e trocam algumas peças. Na hora de emitir a nota eles discriminam os produtos dos serviços, ou seja, em um momento a nota está trabalhando com um objeto produto, em outra ela está trabalhando com um objeto serviço. Produto está sujeito à ICMS, IPI, etc. e serviço está sujeito a ISS. Se as duas classes forem derivadas de uma classe mãe, chamada ItemDaNota, o código da classe NotaFiscal não precisa se preocupar com que classe concreta está trabalhando naquele momento, ela sabe que Produto ou Serviço herdam de ItemDaNota, portanto ela sabe como trabalhar com os dois. Ela pode simplesmente executar um método como calculaImposto, que o item, seja produto ou serviço, saberá como calcular e retornará o valor do seu imposto. De outra forma, você teria que criar dois métodos diferentes para tratar produtos e serviços, além do que teria que manter uma coleção para cada um dos tipos. Usando o polimorfismo você simplifica o seu código e pode usar uma única coleção que conterá os produtos e serviços, pois poderá criar uma coleção de ItemDaNota, e não especificamente de produto ou serviço. Esse é um exemplo ingênuo do que pode ser feito, não sei se deu para entender, qualquer coisa dá um grito aí que a gente tenta explicar melhor.

Sandro.

solução!

Oi Márcio,

A vantagem de você usar a abstração como referência, como é o caso de AreaCalculavel é que você consegue trocar a implementação concreta.

Imagine o seguinte método:

public void fazAlgoCom(AreaCalculavel a) {
    double result = a.calcula();
    // ...
}

Quais tipos são aceitos por esse método? Todos filhos de AreaCalculavel. Isso quer dizer que se amanhã criarmos uma nova figura geométrica, o código acima vai funcionar pra ela também! Você não precisa nem mexer nesse código!

Viu como ele evolui sozinho?

Um abraço!

A vantagem está muito bem explicada acima porem existe uma desvantagem.... como vimos nos exercícios ao instanciarmos uma classe filho a uma classe pai (AreaCalculavel a = new Retangulo(3,2)) só é permitido invocarmos métodos de a que também existam em AreaCaçculavel, logo se quisermos chamar um método exclusivo da classe retângulo não seriamos capasses.

Portanto a utilização da abstração deve sempre ser uma escolha baseada na nescidade atual de seu código

O importante em utilizar interfaces é unir classes distintas de negócio em um método comum.

Oi Cauê,

Essa é a sacada! Isso NAO PODE ser uma desvantagem! Se vc pensar bem na abstração, vc não terá métodos diferentes, na maioria dos casos!

Essa é a graça de um sistema OO, certo? Você precisa modelar! :)

Exatamente como disse o Maurício, inclusive é nisso que se baseia o padrão strategy, usando uma interface ou classe abstrata comum entre várias subclasses.