2013-05-01 4 views

risposta

97
public class Animal { 
    public static void foo() { 
     System.out.println("Animal"); 
    } 
} 

public class Cat extends Animal { 
    public static void foo() { // hides Animal.foo() 
     System.out.println("Cat"); 
    } 
} 

Qui, Cat.foo() si dice per nascondere Animal.foo(). Nascondere non funziona come un override, perché i metodi statici non sono polimorfici. Così il seguente accadrà:

Animal.foo(); // prints Animal 
Cat.foo(); // prints Cat 

Animal a = new Animal(); 
Animal b = new Cat(); 
Cat c = new Cat(); 
Animal d = null; 

a.foo(); // should not be done. Prints Animal 
b.foo(); // should not be done. Prints Animal because the declared type of b is Animal 
c.foo(); // should not be done. Prints Cat because the declared type of c is Cat 
d.foo(); // should not be done. Prints Animal because the declared type of b is Animal 

Calling metodi statici sulle istanze piuttosto che classi è una pessima pratica, e non dovrebbe mai essere fatto.

Confrontate questo con i metodi di istanza, che sono polimorfi e sono quindi sovrascritti. Il metodo chiamato dipende dal calcestruzzo, tipo runtime dell'oggetto:

public class Animal { 
    public void foo() { 
     System.out.println("Animal"); 
    } 
} 

public class Cat extends Animal { 
    public void foo() { // overrides Animal.foo() 
     System.out.println("Cat"); 
    } 
} 

Poi si verifica quanto segue:

Animal a = new Animal(); 
Animal b = new Cat(); 
Animal c = new Cat(); 
Animal d = null; 

a.foo(); // prints Animal 
b.foo(); // prints Cat 
c.foo(); // prints Cat 
d.foo(): // throws NullPointerException 
+15

Risposta molto buona e tu sei l'unico a dire che chiamare i metodi statici su istanze è malvagio. +1 –

+1

il mio dubbio è che puoi ancora accedere al metodo della classe genitore dicendo qualcosa come super.foo giusto? allora qual è il nascondiglio che sta succedendo qui. Sta semplicemente ribadendo il fatto che la funzione chiamata è quella associata alla variabile di riferimento e non all'istanza. Ancora non riesco a capire un bisogno concreto di questa terminologia – JATMON

+7

No. 'super', come' this', non può essere usato in un contesto statico. Puoi chiamare 'Animal.foo()' da 'Cat.foo()', però, ma i due metodi non hanno in realtà nulla in comune, tranne il loro nome e firma. nascondersi è usato per differenziarsi dall'override. Ma nascondere il metodo non è molto utile, mentre il metodo di overhead è una delle parti chiave del design OO. –

1

Ad esempio, è possibile sovrascrivere i metodi di istanza in una classe super ma non statica.

Nascondere è la classe padre ha un metodo statico denominato Foo e la sottoclasse ha anche un metodo statico chiamato Foo.

Un altro scenario è che il genitore ha un metodo statico denominato Cat e la sottoclasse ha un metodo di istanza denominato Cat. (statico e istanza con la stessa firma non possono mescolarsi).

public class Animal { 

    public static String getCat() { return "Cat"; } 

    public boolean isAnimal() { return true; } 
} 

public class Dog extends Animal { 

    // Method hiding 
    public static String getCat() { } 

    // Not method hiding 
    @Override 
    public boolean isAnimal() { return false; } 
} 
2

Per sovrascrivere un metodo significa che ogni volta che il metodo viene chiamato su un oggetto della classe derivata, verrà chiamata la nuova implementazione.

Per nascondere un metodo significa che una chiamata non qualificato che nome nell'ambito di questa classe (cioè nel corpo di uno qualsiasi dei suoi metodi, o quando qualificato con il nome di questa classe) sarà ora chiamare un completamente funzione differente, che richiede una qualifica per accedere al metodo statico con lo stesso nome dalla classe genitore.

Ulteriori descrizione Java Inheritance: Overwritten or hidden methods

1

Se una sottoclasse definisce un metodo di classe con la stessa firma come metodo di classe nella superclasse, il metodo nella sottoclasse nasconde quello della superclasse.

I metodi nascosti sono in contesto statico, credo. I metodi statici non sono sovrascritti, di per sé, perché la risoluzione delle chiamate di metodo fatte dal compilatore al momento della compilazione stesso. Quindi, se si definisce un metodo statico nella classe base con la stessa firma di quello presente nella classe genitore, il metodo nella sottoclasse nasconde il metodo ereditato dalla super classe.

class Foo { 
    public static void method() { 
    System.out.println("in Foo"); 
    } 
} 

class Bar extends Foo { 
    public static void method() { 
    System.out.println("in Bar"); 
    } 
} 
26

Prima di tutto cosa si intende per metodo nasconde?

Metodo nascondere significa sottoclasse ha definito un metodo classe con la stessa firma come metodo di classe nella superclasse. In tal caso il metodo della superclasse è nascosto dalla sottoclasse. Significa che: La versione di un metodo che verrà eseguita sarà NON determinata dall'oggetto utilizzato per richiamarlo. In effetti verrà determinato dal tipo di variabile di riferimento utilizzato per richiamare il metodo.

Cosa si intende per sovrascrittura del metodo?

Metodo imperativa significa sottoclasse aveva definito un metodo esempio con la stessa firma e tipo di ritorno (compresi tipo covariante) come il metodo di istanza in superclasse. In tal caso, il metodo della superclasse viene sovrascritto (sostituito) dalla sottoclasse. Significa che: La versione del metodo che viene eseguita sarà determinata dall'oggetto utilizzato per richiamarlo. Non sarà determinato dal tipo di variabile di riferimento utilizzata per richiamare il metodo.

Perché i metodi statici non possono essere sovrascritti?

Poiché, metodi statici vengono risolti staticamente (cioè in fase di compilazione) in base alla classe che sono chiamati e non dinamico come nel caso con metodi di istanze che vengono risolti polimorfico in base al tipo runtime dell'oggetto .

Come accedere ai metodi statici?

I metodi statici devono essere accessibili in modo statico. cioè dal nome della classe stessa piuttosto che usare un'istanza.

Ecco la breve demo per il metodo prioritario e nascondere:

class Super 
{ 
    public static void foo(){System.out.println("I am foo in Super");} 
    public void bar(){System.out.println("I am bar in Super");} 
} 
class Child extends Super 
{ 
    public static void foo(){System.out.println("I am foo in Child");}//Hiding 
    public void bar(){System.out.println("I am bar in Child");}//Overriding 
    public static void main(String[] args) 
    { 
    Super sup = new Child();//Child object is reference by the variable of type Super 
    Child child = new Child();//Child object is referenced by the variable of type Child 
    sup.foo();//It will call the method of Super. 
    child.foo();//It will call the method of Child. 

    sup.bar();//It will call the method of Child. 
    child.bar();//It will call the method of Child again. 
    } 
} 

uscita è

I am foo in Super 
I am foo in Child 
I am bar in Child 
I am bar in Child 

Chiaramente, come specificato, in quanto foo è il metodo di classe in modo che la versione di foo invocato sarà essere determinato dal tipo di variabile di riferimento (cioè Super o Child) che fa riferimento all'oggetto di Child. Se viene fatto riferimento alla variabile Super, viene chiamato foo di Super. E se viene fatto riferimento alla variabile Child, viene chiamato il numero foo di Child.
considerando,
Poiché bar è il metodo di istanza così la versione di bar richiamato è determinato esclusivamente dall'oggetto (cioè Child) che viene utilizzato per richiamare esso. Indipendentemente da quale variabile di riferimento (Super o Child) viene chiamata, il metodo che verrà chiamato è sempre Child.

Problemi correlati