dúvida em herança

16 respostas
J

pessoal

li em um livro da Kathy Sierra, o seguinte:

class Animal{
    public void eat() throws Exception {
        // lança uma Exception
    }
}
class Dog2 extends Animal{
    public void eat() {
        //nenhuma Exception 
    }
    public static void main(String[] args){
        Animal a = new Dog2();
        Dog2 d = new Dog2();
        a.eat();    // ok
        d.eat();    // erro de compilação - exceção não reportada
    }
}

porém, escrevi este código, compilei e rodei, sem problema algum.
então, minha dúvida é:

  1. eu que não entendi alguma coisa, ou está faltando alguma coisa? se sim, o que?

  2. o livro que está errado?

até onde eu sei, o que não é permitido é o contrário (a subclasse sobrescrever um método da superclasse, incluindo novas exceções verificadas, não declaradas no método do supertipo).

grato

16 Respostas

S

Para mim já deu erro de compilação.
tive que alterar o método para ele compilar.

public static void main(String[] args){ 
        Animal a = new Animal(); 
        Dog2 d = new Dog2(); 
        try {
			a.eat();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}    // ok 
        d.eat();    // erro de compilação - exceção não reportada

estou usando eclipse europa e java 6 ainda estou pensando no que está escrito para tentar entender eheheh

C

Olá amigo, para saber melhor onde está a sua classe de Exception, por favor passe pra gente o capítulo, página, parágrafo e livro no qual está escrito isso.
Na verdade a o que não dá certo ai é quando vc usa a chamada polimórfica, se a sua super classe declara uma excecao verificada, vc terá que tratar com um try mesmo. ok ?

S

Na minha opnião tem coisa errada ai no livro. Na minha opnião o que ela escreveu é diferente do exemplo dado no código.
Você nunca vai conseguir fazer um objeto Dog2 receber um objeto Animal, dessa maneira o subtipo que e quem tem o método sobrescrito só vai conhecer o método eat dele, então o conflito que ela cita ali entre ele tentar chamar o método da superclasse não vai acontecer.
Já quando ela faz Animal = Dog2, é uma atribuição possível, no entanto o objeto Animal não vai absorver o comportamento de Dog2, e por isso que para mim tive que colocar o try/catch no código.

C

Amigo… eu não entendi a sua explicação sobre o polimorfismo ai.
Pode ser mais claro ?

S
Eu não expliquei polimorfismo, mas posso tentar exclarecer o que escrevi.
class Animal{ 
    public void eat() throws Exception { 
       System.out.println("Classe Pai");
    } 
} 
class Dog2 extends Animal{ 
    public void eat() { 
    	System.out.println("Classe Filha"); 
    } 
    public void walk(){}
} 

class heranca{
	
    public static void main(String[] args){ 
        Animal a = new Dog2(); //ta certo
        Dog2 d = new Dog2();//ta certo
        Dog2 b = new Animal();// não compila
    } 
}
beleza, isso é básico.

No livro ela diz

se um método é sobrescrito mas você usa uma rererência polimórfica (referência ao supertipo) para consultar o objeto do subtipo com o método que está sobrescrevendo, o compilador assume que você está chamando a versão do supertipo do método
eu não concordo, pois a superclasse não vai herdar as características da classe filha, basta você tentar fazer um objeto Animal chamar o método walk. COm essa parte do livro eu concordo
se a versão do supertipo declara uma exceção verificada, mas o método que sobrescreveu, no subtipo, não declara, o compilador ainda pensa que você está chamando o método que declara uma exceção. por exemplo:
tanto que tive que colocar o try/catch mas aí no código de exemplo eu não concordo com isso
a.eat();    // ok 
        d.eat();    // erro de compilação - exceção não reportada
para mim os comentários do código estão invertidos
C

“se um método é sobrescrito mas você usa uma rererência polimórfica (referência ao supertipo) para consultar o objeto do subtipo com o método que está sobrescrevendo, o compilador assume que você está chamando a versão do supertipo do método”

eu não concordo, pois a superclasse não vai herdar as características da classe filha, basta você tentar fazer um objeto Animal chamar o método walk.

Eu concordo plenamente com a katty, e mais uma vez não posso concordar com a sua citação de descordância com a katty.

Quem herda, é a SUBclasse, e a SUBclasse HERDA as características da classe mae, salvo quando favor colocar questoes de searilizacao no meio, mas não e o foco da conversa…

J

amigos

desculpem, acho que faltou eu escrever isto…

sim, também tive que incluir um bloco try catch (o qual, não estava mostrado no livro) pra compilar o código, porém, pelo que entendi, o que ela estava dizendo era que o código não compilaria, pois a Exception declarada no método da classe pai, não foi declarada no método da classe filha…

até onde eu sei, o funcionamento é exatamente o contrário, não?

J

perdão, mensagem repetida…

S

Cassolato por favor mostre-nos por quê então a classe Dog2 funciona?

C

Sim… vamos lá…

Vamos partir do princípio do polimorfismo e das exceptions quando tratamos de subClasses ou interfaces…

Na classe…

class abstract class X { void a() throws MyException { System.out.println("vai escrever X"); } }
e temos…

class Y extends X { void a() { System.out.println("Vai escrever Y"); } }

Se voce olhar nos livros, vai estar escrito que…
Uma classe que reimplementa um método de uma superclasse na qual declara uma exception verificada, ele pode NÃO declarar que vai lancala, e NAO PODE declarar que vai lancar uma exeption na arvore de heranca acima da exception que a sua superclasse declarou, ou seja… o metodo a da classe Y nao poderia declarar um thorws pra Exception, isso daria um erro de compilacao certo ?

Bem… agora partindo desse principio…
Quando eu faco…
X x = new Y();
O compilador esta usando a referencia da SuperClasse pra colocar na variavel de referencia, e o metodo a da classe X esta lancando uma exception verificada, ou seja… eu sou OBRIGADO no metodo que vai chamar essa exception, a declarar que o METODO vai lancar essa exception ou tratar com um Try.
Mas c eu tenho…

Y y = new Y();
eu ja estou indo DIRETO pra referencia de uma classe que esta reescrevendo esse metodo, ou seja… se a minha classe nao declarar essa exception no metodo, eu nao vou precisar tratar isso, ok ?

Mais alguma duvida ?

C

“julioromano”:
pessoal

li em um livro da Kathy Sierra, o seguinte:

class Animal{
    public void eat() throws Exception {
        // lança uma Exception
    }
}
class Dog2 extends Animal{
    public void eat() {
        //nenhuma Exception 
    }
    public static void main(String[] args){
        Animal a = new Dog2();
        Dog2 d = new Dog2();
        a.eat();    // ok
        d.eat();    // erro de compilação - exceção não reportada
    }
}

porém, escrevi este código, compilei e rodei, sem problema algum.
então, minha dúvida é:

  1. eu que não entendi alguma coisa, ou está faltando alguma coisa? se sim, o que?

  2. o livro que está errado?

até onde eu sei, o que não é permitido é o contrário (a subclasse sobrescrever um método da superclasse, incluindo novas exceções verificadas, não declaradas no método do supertipo).

grato

O código não compila pois o método eat da classe Animal lança uma exceção, portanto o método main deve tratar ou lançar a exceção para compilar.

O que ocorre é que o método eat substituido em Dog não lança uma exceção superior a Exception, por isso que não ocorre erro.

Tente lançar a exceção Throwable no método eat do Dog para ver o que acontece.

L

Vou me meter tb :razz:

Dog2 funciona porque o compilador sabe que o método que ele vai chamar é na pior das hipóteses um “eat” de uma classe que é subtipo de Dog2 e não pode declarar mais nenhum exception pois “eat” de Dog2 não declara. Quando vc tem uma referencia de Animal, vc tem que tratar a exceção porque Animal pode estar referenciando não somente um Dog2 que não possui exceção, mas também outro animal (Cat2) que pode lançar.

E se o supertipo não chamar o método do subtipo (no caso quando a referencia for Animal o compilador sempre chamar o eat de animal), ai perde-se boa parte da vantagem que se tem com polimorfismo.

J

“Carneiro”:
“julioromano”:
pessoal

li em um livro da Kathy Sierra, o seguinte:

class Animal{
    public void eat() throws Exception {
        // lança uma Exception
    }
}
class Dog2 extends Animal{
    public void eat() {
        //nenhuma Exception 
    }
    public static void main(String[] args){
        Animal a = new Dog2();
        Dog2 d = new Dog2();
        a.eat();    // ok
        d.eat();    // erro de compilação - exceção não reportada
    }
}

porém, escrevi este código, compilei e rodei, sem problema algum.
então, minha dúvida é:

  1. eu que não entendi alguma coisa, ou está faltando alguma coisa? se sim, o que?

  2. o livro que está errado?

até onde eu sei, o que não é permitido é o contrário (a subclasse sobrescrever um método da superclasse, incluindo novas exceções verificadas, não declaradas no método do supertipo).

grato

O código não compila pois o método eat da classe Animal lança uma exceção, portanto o método main deve tratar ou lançar a exceção para compilar.

O que ocorre é que o método eat substituido em Dog não lança uma exceção superior a Exception, por isso que não ocorre erro.

Tente lançar a exceção Throwable no método eat do Dog para ver o que acontece.

entao, a única coisa que falta é um try catch, por exemplo?

C

Ou então lançar a exceção.

J

nesse ponto, eu concordo…
achei que o livro tivesse um erro, pois entendi que tava dizendo que o errado seria o método na classe pai, declarar uma Exception, que o método que sobrescreveu, na classe filha, não declarou…

C

Já li varios livros da katty, e acho meio difícil ela errar…

Criado 20 de dezembro de 2007
Ultima resposta 21 de dez. de 2007
Respostas 16
Participantes 5