Polimorfismo


class SuperException extends Exception {}
class SubException extends SuperException {}

class AnotherException extends Exception {}
class YetAnotherException extends Exception {}

class A {
  void play() throws SuperException, AnotherException {}

class Eliminated extends A {
  void play() {} // eliminated
}

public class TestPolymorphism {
  public static void main(String[] args) {
    A obj = new Eliminated();
    obj.play();  // compile error, because 
                 // compiler expects it may throw 
                 // SuperException, AnotherException
  }
}

O programa acima gera um erro na linha 17.

Eu estou utilizando polimorfismo. O método play() foi sobrescrito na classe Eliminated para não lançar nenhuma exceção. Quando acesso métodos na main utilizando uma variável de superclasse recebendo um objeto de subclasse, espero poder acessar apenas os métodos que a superclasse declara, mas acessar esses métodos atualizados, ou seja, ao invés de acessar os métodos da superclasse, acessar os métodos da subclasse. Se é isso que ocorre e se eu sobrescrevi o método play() para não lançar exceção, porque a JVM reclama dizendo que o meu método pode lançar uma exceção?

Logicamente, se eu acessar play() através de uma variável de subclasse, o erro desaparece.

Esse negócio de “saber o método atualizado” não é bem assim.

A JVM sabe o método certo para invocar em tempo de execução. Em tempo de compilação ele vai assumir que qualquer versão desse método possa lançar a exceção. Afinal, essa é a assinatura que ele está avaliando.

Pelo o que eu entendi você declarou na class pai que o método vai lançar exception, então você não pode simplesmente retirar essa exception do filho.
Seria por exemplo mudar o tipo de acesso(public, private, protected) de uma método herdado.

[quote=Rodrigo Sasaki]Esse negócio de “saber o método atualizado” não é bem assim.

A JVM sabe o método certo para invocar em tempo de execução. Em tempo de compilação ele vai assumir que qualquer versão desse método possa lançar a exceção. Afinal, essa é a assinatura que ele está avaliando.[/quote]

É verdade…

Em tempo de compilação ele verifica se o método existe na classe o qual eu o estou chamando. Como o tipo é da superclasse e nela a assinatura indica que lança exceção, o compilador reclama. Contudo, o método chamado é o sobrescrito.

Obrigado pelo toque…falta de atenção!

[quote=ghpm99]Pelo o que eu entendi você declarou na class pai que o método vai lançar exception, então você não pode simplesmente retirar essa exception do filho.
Seria por exemplo mudar o tipo de acesso(public, private, protected) de uma método herdado.[/quote]

Eu posso pelo princípio de “o método de subclasse pode lançar uma subclasse de exceção verificada declarada pelo método da superclasse, ou não lançar nenhuma”.
Como a exceção que declaro na superclasse é verificada, a sobrescrita desse método não pode lançar uma exceção mais genérica que ela, mas pode não lançar nenhuma exceção. Convém lembrar que eu poderia ter lançado exceções não verificadas no método sobrescrito da subclasse sem nenhum problema. A regra é apenas para exceções verificadas.

só uma coisinha, esta faltando um } ahsuahsuahsuahsauhs
mas acho que entendi o que voce quis dizer, o que voce vai ter que fazer no caso é colocar o obj.play dentro de um try/catch.

[code]class SuperException extends Exception {}
class SubException extends SuperException {}

class AnotherException extends Exception {}
class YetAnotherException extends Exception {}

class Inicio {

  public static void main(String[] args) {  
    AA obj = new Eliminated();  
    
		try {
			obj.play();
		} catch (SuperException e) {			
			e.printStackTrace();
		} catch (AnotherException e) {				
			e.printStackTrace();
		}		
  }  
}

class AA {
void play() throws SuperException, AnotherException {
System.out.println(“entrou AA”);
}
}
class Eliminated extends AA {
void play() {
System.out.println(“entrou Eliminated”);
}
} [/code]

se rodar esse código vai imprimir “entrou Eliminated”