Herança de classe abstrata com um método estático

3 respostas
certificacoesprogramaçãojava
L

Achei esse exemplo na Internet e gostaria de saber porquê ao rodar o programa ele imprime Writing e não Writing Code?

abstract class Writer {

public static void write() {

System.out.println(Writing…”);

}

}
class Author extends Writer {

public static void write() {

System.out.println(Writing book);

}

}
public class Programmer extends Writer {

public static void write() {

System.out.println(Writing code);

}
public static void main(String[] args) {
	Writer w = new Programmer();
	w.write();
}

}

3 Respostas

L

Então ele deveria imprimir o que está definido no método write em Programmer que não é o caso.

D

Métodos statics são da classe e não do objeto:

abstract class Writer {
 public static void write() {
  System.out.println("Writing…");
 }
 public static void writeChar(char c) {
  System.out.println("Writing… " + c);
 }
}
class Author extends Writer {
 public static void write() {
  System.out.println("Writing book");
 }
}
public class Programmer extends Writer {
 public static void write() {
  System.out.println("Writing code");
 }
 public static void main(String[] args) {
  Writer w = new Programmer();
  w.write(); // Writing… (da classe Writer, pois w é do tipo Writer)
  Programmer p = (Programmer) w;
  p.write(); // Writing code (da classe Programmer, pois p é do tipo Programmer)
  p.writeChar('A'); // Writing… A (da classe Writer, pois Programmer não tem esse método)
 }
}

Se os métodos não fossem statics a saída seria:

Writing code
Writing code
Writing A
W

O comportamento difere entre métodos de classe e métodos de instancia.

É dito que um método de instancia é sobreescrito (overriding) enquanto que um método de classe é apenas escondido (hiding).

Você pode ler mais detalhes aqui:

https://docs.oracle.com/javase/tutorial/java/IandI/override.html

E aqui:

https://docs.oracle.com/javase/specs/jls/se10/html/jls-8.html#jls-8.4.8

Mas em resumo:

  • Um método de classe é invocado com base no tipo da variável que o contém.
  • Um método de intancia é invocado com base no tipo do objeto instanciado nesta variável.

Sendo assim:

class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal");
    }
}

class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Cat");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;

        myAnimal.testClassMethod();         // "The static method in Animal"
        myAnimal.testInstanceMethod();      // "The instance method in Cat"
        // Para invocar o estático de Cat, só com casting
        ((Cat) myAnimal).testClassMethod(); // "The static method in Cat"
    }
}

De qualquer forma, é recomendado que ao acessar métodos estáticos, use o nome da classe e não do objeto. Ou seja:

Writer.write();
// ou
Programmer.write();

Ao invés de:

new Writer().write();
// ou
new Programmer().write();

Obs: Ao postar código, utilize as tags corretas para melhor visualização de todos. Em caso de duvidas, este tópico pode ajudar.

Criado 16 de maio de 2018
Ultima resposta 16 de mai. de 2018
Respostas 3
Participantes 3