2016-07-21 1 views
1
public class Imp1 implements Inter1 { 
    private int num; 

    @Override 
    public void apply() { 
     num++; 
    } 

    public void doubler() { 
     num = num * 2; 
    } 

    public boolean equals(Imp1 o) { 
     if (!(o instanceof Imp1)) 
      return false; 
     return o.num == num; 
    } 

    public int getNum() { 
     return num; 
    } 

    public static void main(String[] args) { 
     final Inter1 a = new Imp1(); 
     final Imp1 b = new Imp1(); 
     a.apply(); 
     b.apply(); 
     System.out.println("a equals b " + a.equals(b)); 
     System.out.println("b equals a " + b.equals(a)); 
    } 

} 

Ich würde erwarten, equals(Imp1 o) für a.equals(b) und b.equals(a) als den besten Kandidaten gewählt werden, warum ist es hier nicht der Fall?Warum Überlastung mit param des Unterklassentypen wird über einige Elternklassen nicht gewaehlt

In mehr Details - dieser Code gibt zweimal falsch aus und ich frage mich warum? a und b hält Imp1-Objekt, daher Aufruf gleich mit Imp1-Instanz als param sollte equals(Imp1 o) aufrufen, die besser als equals(Object o) passt, aber ich sehe, dass equals(Object o) aufgerufen wird, und schließlich der Code zweimal falsch statt zweimal true.

Antwort

1

Die Auflösung der Methodenüberladung wird durch den Kompilierzeittyp der Argumente bestimmt, da der Compiler die am besten passende Methodensignatur zum Zeitpunkt der Kompilierung auswählt.

equals(Imp1 o) kann nur gewählt werden, wenn der Kompilierzeittyp des an die Methode übergebenen Arguments Imp1 oder eine Unterklasse von Imp1 ist.

a erfüllt dieses Kriterium nicht, so b.equals(a) ruft Object 's equals.

Was a.equals(b), da die Kompilierung Art von a nicht Imp1 ist, ist es die equals(Imp1 o) Methode nicht aufrufen kann (es sei denn Sie es Impl1 cast), so dass es nur Object ‚s equals wählen können.

System.out.println("a equals b " + ((Imp1)a).equals(b)); 

wird equals(Imp1 o) anrufen.

+0

und was a.equals (b) ?, es auch falsch druckt !! –

+0

@OfekRon bearbeitet Antwort – Eran

+0

aber Java überschreiben ist virtuell in C++ - Jargon, dies bedeutet, dass die tatsächliche Methode aufgerufen werden muss, ist der der Instanzklasse nicht der Referenztyp Klasse –

1

Das Problem ist, Sie überschreiben nicht wirklich die Gleichen der Superklasse Objekt!

Dies ist der richtige Weg, dies zu tun:

public class Imp1 implements Inter1 { 
private int num; 

@Override 
public void apply() { 
    num++; 
} 

public void doubler() { 
    num = num * 2; 
} 

@Override//<-----need to override the equals of the superClass Object!!! 
public boolean equals(Object o) {//<---must be Object!!! 
    if (!(o instanceof Imp1)) 
     return false; 
    return ((Imp1)o).num == num; 
} 

public int getNum() { 
    return num; 
} 

public static void main(String[] args) { 
    final Inter1 a = new Imp1(); 
    final Imp1 b = new Imp1(); 
    a.apply(); 
    b.apply(); 
    System.out.println("a equals b " + a.equals(b)); 
    System.out.println("b equals a " + b.equals(a)); 
} 

} 

OR:

public class Imp1 implements Inter1 { 
    private int num; 

    @Override 
    public void apply() { 
     num++; 
    } 

    public void doubler() { 
     num = num * 2; 
    } 

    @Override //<---------------need to be implemented from the interface! 
    public boolean equals(Inter1 o) {//<----the class must to be from the specific interface!!! 
     if (!(o instanceof Imp1)) 
      return false; 
     return ((Imp1)o).num == num;//<-----must to cast the object to the specific object in the "if" 
    } 

    public int getNum() { 
     return num; 
    } 

    public static void main(String[] args) { 
     final Inter1 a = new Imp1(); 
     final Imp1 b = new Imp1(); 
     a.apply(); 
     b.apply(); 
     System.out.println("a equals b " + a.equals(b)); 
     System.out.println("b equals a " + b.equals(a)); 
    } 

} 
Verwandte Themen