Classes Internas (Java)/Gato e Estômago/Classe externa implementa interface

From Wiki**3

< Classes Internas (Java)‎ | Gato e Estômago

O primeiro exemplo, Gato1, é como o que se definiu acima: ilustra-se aqui a possibilidade (já presente) de utilização externa da classe interna.

O segundo caso, Gato2, é idêntico a Gato1, mas implementa a interface Gato, podendo observar-se algumas diferenças na utilização, especialmente no que respeita à utilização de downcasts.

Classe Gato1

Esta classe é a mesma do exemplo anterior: apenas se alterou o nome. Note-se que esta classe não implementa a interface Gato, embora seja compatível.

 public class Gato1 {
   private boolean _comFome = true;
 
   class Estômago {
     private double _ph = 1.4;
     Estômago() { System.out.println("Estômago criado"); }
     void digere() {
       System.out.println("Digestão");
       _comFome = false;
     }
   }
 
   Gato1() { System.out.println("Gato criado"); }
   public boolean temFome() { return _comFome; }
   public void comer() {
     System.out.println("Gato: a comer...");
     Estômago e = new Estômago();
     e.digere();
   }
 }

Interface Gato

A interface que um gato deve implementar.

 interface Gato {
   void comer();
   boolean temFome();
 }

Classe Gato2

Esta classe implementa a interface Gato. À parte esta relação com a interface, é idêntica a Gato1.

 public class Gato2 implements Gato {
   private boolean _comFome = true;
 
   class Estômago {
     private double _ph = 1.4;
     Estômago() { System.out.println("Estômago criado"); }
     void digere() {
       System.out.println("Digestão");
       _comFome = false;
     }
   }
 
   Gato2() { System.out.println("Gato criado"); }
   public boolean temFome() { return _comFome; }
   public void comer() {
     System.out.println("Gato: a comer...");
     Estômago e = new Estômago();
     e.digere();
   }
 }

Teste

 public class Teste2 {
   public static void main(String[] args) {
     Gato1 g1 = new Gato1();
     System.out.println("Gato 1 com fome: " + g1.temFome());
 
     //--- coisas estranhas...?
     // Gato1.Estômago e1 = new Estômago();           // erro: "Estômago" desconhecido
     // Gato1.Estômago e1 = new Gato1.Estômago();     // erro: "e1" sem contexto
     Gato1.Estômago e1 = g1.new Estômago();           // ok: "e1" é o estômago de "g1"
     e1.digere();
     System.out.println("Gato 1 com fome: " + g1.temFome());
 
     Gato g2 = new Gato2();
     System.out.println("Gato 2 com fome: " + g2.temFome());
 
     //--- coisas estranhas...?
     // Gato2.Estômago e2 = new Estômago();       // erro: "e2" sem contexto
     // Gato2.Estômago e2 = g2.new Estômago();    // erro: "g2" é "Gato" e não "Gato2"
     Gato2.Estômago e2 = ((Gato2)g2).new Estômago();    // ok: "e2" é o estômago de "g2"
     e2.digere();
 
     System.out.println("Gato 2 com fome: " + g2.temFome());
   }
 }

Resultado

 $ java Teste2
 Gato criado      (corresponde a g1)
 Gato 1 com fome: true
 Estômago criado
 Digestão
 Gato 1 com fome: false
 Gato criado      (corresponde a g2)
 Gato 2 com fome: true
 Estômago criado
 Digestão
 Gato 2 com fome: false
 $ ls
 Gato.java Gato.class
 Gato1.java Gato1.class Gato1$Estômago.class
 Gato2.java Gato2.class Gato2$Estômago.class
 Teste2.java Teste2.class