Dúvida sobrescrição SCJP 1.6

Novamente estudando pelo livro… Na parte de sobrescrição de métodos, o livro coloca a seguinte regra:

  • Você não pode sobrescrever um método marcado com static.

Mas aih eu fiz o teste no eclipse com o seguinte código:

class Animal{
public static void eat(){
System.out.println(“Animal generico comendo genericamente”);
}
}

class Horse extends Animal{
public static void eat(){
System.out.println(“Cavalo comendo”);
}
}

public class TestAnimals {

public static void main(String[] args) {
	Animal a = new Animal();
	Horse h = new Horse();
	a.eat();
	h.eat();
}

}

Que compila sem erros e mostra a saída:

Animal generico comendo genericamente
Cavalo comendo

Afinal, um método marcado com static pode ou não ser sobrescrito? Se cair uma pergunta dessas no exame, devo responder o q?

Um método marcado static não pode ser sobrescrito, mas pode ser redefinido.
Baseado no exemplo que você postou acima, sto implica no seguinte:

public static void main(String[] args) {

Animal a= new Horse();
a.eat();  //em tempo de execução, se o método eat não for static, a jvm executa a versão da classe cavalo. Porém, se o método for static, a versão executada é a da classe Animal.

} 

[quote=rod.attack]Um método marcado static não pode ser sobrescrito, mas pode ser redefinido.
Baseado no exemplo que você postou acima, sto implica no seguinte:

[code]
public static void main(String[] args) {

Animal a= new Horse();
a.eat(); //em tempo de execução, se o método eat não for static, a jvm executa a versão da classe cavalo. Porém, se o método for static, a versão executada é a da classe Animal.

}
[/code][/quote]

Por acaso estou estudando este capítulo também… :slight_smile:

Rod, isto significa que se o código fosse escrito assim:

[code]class Animal{
public static void eat(){
System.out.println(“Animal generico comendo genericamente”);
}
}

class Horse extends Animal{
public static void eat(){
System.out.println(“Cavalo comendo”);
}
}

public class TestAnimals {

public static void main(String[] args) {
Animal a = new Animal();
Animal h = new Horse(); //Antes estava como Horse h = new Horse()
a.eat();
h.eat();
}
}[/code]

Ele não iria compilar porque h.eat() estaria chamando o método eat() definido como static na classe Horse?
E uma outra pergunta: Caso o método eat() na classe Animal não fosse marcado como static, h.eat() chamaria o método na classe Animal?

[quote=Lys Marie][quote=rod.attack]Um método marcado static não pode ser sobrescrito, mas pode ser redefinido.
Baseado no exemplo que você postou acima, sto implica no seguinte:

[code]
public static void main(String[] args) {

Animal a= new Horse();
a.eat(); //em tempo de execução, se o método eat não for static, a jvm executa a versão da classe cavalo. Porém, se o método for static, a versão executada é a da classe Animal.

}
[/code][/quote]

Por acaso estou estudando este capítulo também… :slight_smile:

Rod, isto significa que se o código fosse escrito assim:

[code]class Animal{
public static void eat(){
System.out.println(“Animal generico comendo genericamente”);
}
}

class Horse extends Animal{
public static void eat(){
System.out.println(“Cavalo comendo”);
}
}

public class TestAnimals {

public static void main(String[] args) {
Animal a = new Animal();
Animal h = new Horse(); //Antes estava como Horse h = new Horse()
a.eat();
h.eat();
}
}[/code]

Ele não iria compilar porque h.eat() estaria chamando o método eat() definido como static na classe Horse?
E uma outra pergunta: Caso o método eat() na classe Animal não fosse marcado como static, h.eat() chamaria o método na classe Animal?[/quote]

Um método marcado static, em tempo de execução, é chamado de acordo com o tipo da variável de referência. Ao contrário de um método de instância, que, em tempo de execução, é chamado de acordo com o tipo do objeto.

Ou seja, nesse exemplo h.eat() compilaria e rodaria sem problema nenhum. Por se tratar de um método estático, a JVM executa a versão do método contido na classe da variável de referência.

Regras:
1 - Quando um método é declarado como static, diz-se que ele é um método da classe, pertencente a classe.
2 - Estático - algo que não muda; não é dinâmico; constante.
3 - Um método estático não muda o resultado de seu processamento conforme a instância do objeto.
4 - Métodos estáticos não são herdáveis nem sobrescritos.
5 - Se um filho redefine um métodos estático do pai, ele está escondendo o acesso ao método pai. A isto se chama sobreamento ( Shadowing)

Não esquece que isto Animal h = new Horse(); ou isso Animal a = new Animal(); - referencia a classe Animal e a um novo objeto Horse() ou Animal().
Então advinha? métodos static pertencem a classe e não ao objeto certo?
então vai imprimir: Animal genérico comendo genericamente

Isto Horse h = new Horse(); criando um novo Objeto horse, com a referencia da classe Horse.
Então advinha? h.eat(); vai fazer a chamada a classe horse.
então vai imprimir: Cavalo comendo

Me Corrijam se eu estiver errado.

[quote=taaqui]Regras:
1 - Quando um método é declarado como static, diz-se que ele é um método da classe, pertencente a classe.
2 - Estático - algo que não muda; não é dinâmico; constante.
3 - Um método estático não muda o resultado de seu processamento conforme a instância do objeto.
4 - Métodos estáticos não são herdáveis nem sobrescritos.
5 - Se um filho redefine um métodos estático do pai, ele está escondendo o acesso ao método pai. A isto se chama sobreamento ( Shadowing)

Não esquece que isto Animal h = new Horse(); ou isso Animal a = new Animal(); - referencia a classe Animal e a um novo objeto Horse() ou Animal().
Então advinha? métodos static pertencem a classe e não ao objeto certo?
então vai imprimir: Animal genérico comendo genericamente

Isto Horse h = new Horse(); criando um novo Objeto horse, com a referencia da classe Horse.
Então advinha? h.eat(); vai fazer a chamada a classe horse.
então vai imprimir: Cavalo comendo

Me Corrijam se eu estiver errado.
[/quote]

Exato. Foi o que disse acima.

sei q muita gente ja respondeu, mas tentando ser sucinto…

é possivel redefinir métodos estaticos, mais nunca sobrescrever, o que vc fez não sobrescreveu o método, tanto que se vc fizer uma pequena alteração no seu código

de Animal a = new Animal(); Horse h = new Horse(); a.eat(); h.eat(); paraAnimal a = new Animal(); Animal h = new Horse(); a.eat(); h.eat(); //vera que aqui imprimirar o mesmo que Animal.eat()... pois a referencia h é de um Animal, mesmo ela conendo um Horse //sendo assim não há sobrescrição e sim redefinição

Não funciona!!!
Se vc tirar a palavra static da classe Animal, a classe Horse herdará este método.

Eu testei e o compilador dá a mensagem: This static method cannot hide the instance method from Animal

Se alguém tiver uma explicação melhor pq não funciona, nos ajude ai.

Abraço.

Não funciona!!!
Se vc tirar a palavra static da classe Animal, a classe Horse herdará este método.

Eu testei e o compilador dá a mensagem: This static method cannot hide the instance method from Animal

Se alguém tiver uma explicação melhor pq não funciona, nos ajude ai.

Abraço.[/quote]

não funciona pq vc so modificou em uma das classes… esse erro esta falando o seguinte

public class Animal { public void eat() {} }

public class Horse extends Animal { public static void eat() {} //iso aqui é impossivel, pois Horse já tem um método public void eat() erdado de Animal //por isso não se pode definir outro estatico, esse foi o erro q vc obteve... }

porem uma classe Horse como abaixo, funcionaria perfeitamente…

public class Horse extends Animal { public void eat() {} }

pronto… agora funciona… e para esse segundo caso

Animal h = new Horse();

onde vc fizesse

h.eat(); ira chamar o eat() de Horse, e não o de Animal, pois mesmo sendo h uma variável Animal, métodos de instancia são chamados sempre de acordo com a instancia alocada na referencia, que no caso é um Horse…