É possível chamar methods de subclasss em um object de superclass?

Animal é uma superclass de Dog and Dog tem um método chamado bark

public void bark() { System.out.println("woof"); } 

Considere o seguinte:

 Animal a = new Dog(); if (a instanceof Dog){ a.bark(); } 

O que vai acontecer?

  1. a tarefa não é permitida
  2. a chamada para latir é permitida e “woof” é impresso em tempo de execução
  3. a chamada para latir é permitida mas nada é impresso
  4. a chamada para latir causa um erro de tempo de compilation
  5. a chamada para latir resulta em um erro de tempo de execução

Eu disse 2 enquanto estamos checando se o object é um cachorro; como o cão é a class com o método da casca, se é assim, nós o chamamos, o qual imprimirá: s

Meu entendimento está correto aqui?

    Isso não será compilado, já que Animal não possui um método chamado bark. Pense desta maneira, todos os cães são animais, mas nem todos os animais são cães. Todos os cães latem, mas nem todos os animais latem.

    não – a resposta é;

    4) a chamada para latir causa um erro de tempo de compilation

    o método de casca não é definido como um método no tipo designado Animal, o que resultará em problema de tempo de compilation; isso poderia ser resolvido por fundição;

     ((Dog)a).bark(); 

    A chave está na seguinte linha:

     Animal a = new Dog(); 

    Embora uma nova instância de Dog sido criada, sua referência é por a que é declarado como sendo do tipo Animal . Portanto, qualquer referência a a faz o new Dog ser tratado como Animal .

    Portanto, a menos que Animal tenha um método de bark , a linha a seguir causará um erro no compilador:

     a.bark(); 

    Mesmo que a seja testado para ver se é uma instância de Dog , e a instanceof Dog realmente retornará true , a variável a ainda é do tipo Animal , então o bloco dentro da instrução if ainda manipula a como Animal .

    Esta é uma característica de linguagens estaticamente tipadas onde as variables ​​recebem um tipo antes do tempo, e checadas em tempo de compilation para ver se os tipos combinam. Se esse código foi executado em uma linguagem tipificada dinamicamente , onde os tipos são verificados em tempo de execução, algo como o seguinte pode ser permitido:

     var a = new Dog(); if (a instanceof Dog) a.bark(); 

    a.bark() é garantido apenas para executar quando a instância é um Dog , então a chamada para bark sempre funcionará. No entanto, Java é uma linguagem com tipagem estática, portanto, esse tipo de código não é permitido.

    No Head First Java eles usam a muito boa analogia de um controle remoto de TV para uma referência e sua TV como o object para o qual a referência aponta. Se o seu controle remoto tiver apenas botões (methods) para ligar, desligar, canal para cima e para baixo e volume para cima e para baixo, não importa quais resources interessantes sua TV tenha. Você ainda pode fazer apenas algumas coisas básicas do seu controle remoto. Você não pode silenciar sua TV, por exemplo, se seu controle remoto não tiver botão mudo.

    A referência Animal só conhece os methods animais. Não importa quais outros methods o object subjacente tenha, você não pode acessá-los a partir de uma referência Animal.

    É 4. Você não pode pedir a um Animal genérico – que é o que seu código diz que é – latir. Porque você poderia facilmente dizer

     Animal a = new Cat(); 

    e a linha de casca não tem como saber que você não sabia.

    Se a idéia é imprimir o método subclass do object superclass, isso funcionará:

    Em vez de Animal a = new Dog(); if (a instanceof Dog){ a.bark(); } Animal a = new Dog(); if (a instanceof Dog){ a.bark(); } Animal a = new Dog(); if (a instanceof Dog){ a.bark(); } mudar para

     Animal a = new Dog(); if (a instanceof Dog){ Dog d = (Dog) a; d.bark(); } 

    Isso lança a superclass de volta para a subclass e a imprime. apesar de seu design ruim, é uma maneira de saber qual object de class filho está apontando dinamicamente.

    FYI, isso não é um bom design.

    Apenas a qualquer momento você tem código deste formulário:

     if (x instanceof SomeClass) { x.SomeMethod(); } 

    você está abusando do sistema de tipos. Esta não é a maneira de usar classs, não é a maneira de escrever código orientado a object sustentável. É frágil. É complicado. É mau.

    Você pode criar methods de modelo em uma class base, mas eles precisam chamar methods que existem na class base e são substituídos em subclasss.

    Em java (somente na língua que conheço) você pode criar um método vazio e chamá-lo em superclass. Então você pode sobrescrevê-lo na subclass para fazer o que quiser. Desta forma, a superclass chama seu método de subclass.

     public class Test { public static void main(String[] args){ Snake S = new Snake(); Dog d = new Dog(); } } class Animal{ //Super Class public Animal(){ bark(); //calls bark when a new animal is created } public void bark(){ System.out.println("this animal can't bark"); } } class Dog extends Animal{ //Subclass 1 @Override public void bark(){ System.out.println("Woof"); } } class Snake extends Animal{//Subclass 2 public void tss(){ } } 

    Este código chama um object de Snake e chama um object de Dog. Ele grava isso no console:

     this animal can't bark Woof 

    Snake não tem nenhum método de casca, então o método super class é chamado. Ele escreve a primeira linha no console. O cachorro tem um método de casca, então a class super o chama. Ele escreve a segunda linha no console.

    “Eu disse 2 quando estamos checando se o object é um cachorro; como cão é a class com o método de casca, se é assim, nós o chamamos, o que será impresso: s”

    Seu raciocínio está correto, mas não é assim que funciona.

    Java é uma linguagem tipada estática que significa que a validade dos methods aos quais um object pode responder é verificada em tempo de compilation .

    Você pode pensar no cheque:

     if( a instanceof Dog ) 

    Faria, mas na verdade isso não acontece. O que o compilador faz é checar contra a “interface” do tipo declarado (Animal neste caso). A “interface” é composta pelos methods declarados na class Animal.

    Se o método bark () não estiver definido no super class Animal, o compilador diz: “Ei, isso não funciona”.

    Isso é útil, porque “às vezes” fazemos erros ao codificar (digitando barck (), por exemplo)

    Se o compilador não nos avisar sobre isso, você teria que encontrá-lo em “runtime” e nem sempre com uma mensagem clara (por exemplo, o javascript no IE diz algo como “object inesperado”)

    Ainda assim, a linguagem tipada estática como o java nos permite forçar a chamada. Neste caso, está usando o operador “cast” ()

    Como isso

     1. Animal a = new Dog(); 2. if (a instanceof Dog){ 3. Dog imADog = ( Dog ) a; 4. imADog.bark(); 5. } 

    Na linha 3 você está “lançando” para um tipo de cachorro, então o compilador pode verificar se a casca é uma mensagem válida.

    Esta é uma instrução para o compilador dizendo “Ei, eu sou o programador aqui, sei o que estou fazendo”. E o compilador, verifica, Ok, cachorro, pode receber a mensagem bark (), prossiga. No entanto, se em tempo de execução o animal não for um cão, uma exceção de tempo de execução será aumentada.

    O casting também pode ser abreviado como:

     if( a instanceof Dog ) { ((Dog)a).bark(); } 

    Isso vai correr.

    Então, a resposta correta é 4:a chamada para latir causa um erro de tempo de compilation

    Eu espero que isso ajude.