1. Mas isso não é tudo.

Suponha que a Cowclasse tenha um printAll()método que chama dois outros métodos. Então o código funcionará assim:

Código Descrição
class Cow
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor ()
   {
      System.out.println("I'm a white whale");
   }

   public void printName()
   {
      System.out.println("I'm a cow");
   }
}

class Whale extends Cow
{
   public void printName()
   {
      System.out.println("I'm a whale");
   }
}
public static void main(String[] args)
{
   Whale whale = new Whale ();
   whale.printAll();
}
A saída da tela será:
I'm a white whale
I'm a whale

Observe que quando o printAll()método da Cowclasse é chamado em um Whaleobjeto, o printNamemétodo daWhale classe é usado, não o do Cowmétodo.

O principal não é a classe em que o método é escrito, mas sim o tipo (classe) do objeto no qual o método é chamado.

Somente métodos não estáticos podem ser herdados e substituídos. Os métodos estáticos não são herdados e, portanto, não podem ser substituídos.

Aqui está a Whaleaparência da classe depois de aplicar a herança e a substituição do método:

class Whale
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor()
   {
      System.out.println("I'm a white whale");
   }

   public void printName()
   {
      System.out.println("I'm a whale");
   }
}
Aqui está a Whaleaparência da classe após a aplicação da herança e substituição de método: Não conhecemos nenhum printNamemétodo antigo.

2. Datilografia

Há um ponto ainda mais interessante aqui. Como uma classe herda todos os métodos e dados de sua classe pai, uma referência a um objeto da classe filha pode ser armazenada em (atribuída a) variáveis ​​cujo tipo é o mesmo da classe pai (e do pai do pai, etc. — todo o caminho até a Objectaula). Exemplo:

Código Descrição
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printColor();
}
A saída da tela será:
I'm a white whale
public static void main(String[] args)
{
   Cow cow = new Whale();
   cow.printColor();
}
A saída da tela será:
I'm a white whale
public static void main(String[] args)
{
   Object o = new Whale();
   System.out.println(o.toString());
}
A saída da tela será:
Whale@da435a.

O toString()método é herdado da Objectclasse

Esta é uma propriedade muito valiosa: um pouco mais tarde você entenderá como usá-la na prática.


3. Chamando um método em um objeto

Quando um método é chamado em uma variável, o método é realmente chamado em um objeto. Esse mecanismo é chamado de envio de método dinâmico.

Veja como fica:

Código Descrição
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printName();
}
A saída da tela será:
I'm a whale
public static void main(String[] args)
{
   Cow cow = new Whale();
   cow.printName();
}
A saída da tela será:
I'm a whale

Observe que a implementação específica do printName()método que é chamado — o da classe Cowou o da Whaleclasse — não é determinado pelo tipo da variável, mas pelo tipo do objeto ao qual a variável se refere.

A Cowvariável armazena uma referência a um Whaleobjeto, e o printName()método definido na Whaleclasse é o que é chamado.

Isso não é muito óbvio. Lembre-se da regra principal:

O conjunto de métodos disponíveis para serem chamados em uma variável é determinado pelo tipo da variável. E a implementação do método específico que é chamado é determinada pelo tipo/classe do objeto referido pela variável.

Você vai encontrar isso o tempo todo, então quanto mais cedo você se lembrar disso, melhor.