2015-06-07 29 views
5

Czy ktoś może wyjaśnić mi wynik tej egzekucji? Nie mogę zauważyć, dlaczego każda metoda jest wywoływana. I jak odróżniamy prawdziwy typ od pozornego typu. Dziękuję :)Dziedziczenie w Javie, pozorny typ kontra rzeczywisty typ

public class JavaApplication15 { 
    public static void main(String[] args) { 
     A a = new A(); 
     B b= new B(); 
     A ab = new B(); 
     b.f(a); 
     b.f(b); 
     b.f(ab); 
    } 
} 

public class A { 
    private final String id="A"; 
    public void f(A x){ 
    System.out.println("Send a fax to "+ x) ; 
    } 
    public String toString(){return id;} 
} 

public class B extends A{ 
    private final String id="B"; 
    public void f(B x){ 
    System.out.println("Send an email to"+ x) ; 
    } 
    public String toString(){return id;} 
} 

Wynik:

Send a fax to A 
Send an email to B 
Send a fax to B 

Odpowiedz

3

Jesteś overloading który (na Wikipedii) tworzy wiele metod o tej samej nazwie z różnymi implementacjami. Myślę, że miałeś na myśli override metodę f(A x) za pomocą metody f(B x). Przesłonięcie (na wikipedii) pozwala klasie podklasy lub klasie podrzędnej na zapewnienie określonej implementacji metody, która jest już dostarczona przez jedną z jej nadklas lub klas nadrzędnych.

oparciu o zaskoczeniu wyrażonej w swoje pytanie, myślę, że chciał coś

@Override 
public void f(A x) { 
    System.out.println("Send an email to"+ x) ; 
} 
2
@Override 
public String toString() 
{ 
    return id; 
} 

ten określa, jak klasa jest wyprowadzany. Podczas wywoływania funkcji, takiej jak:

b.f(a) 

Wprowadzasz klasę jako parametr. Ze względu na twoją metodę toString(), która jest nadpisaniem standardowej metody wyprowadzania twojej klasy, wyświetlasz id po Send an email to.

1

Od rozszerza A, a A ma metodę publiczną. Więc ma obie z następujących metod -

public void f(A x){ 
    System.out.println("Send a fax to "+ x) ; 
} 

oraz -

public void f(B x){ 
    System.out.println("Send an email to"+ x) ; 
} 

Właściwie seond metoda B jest przeciążona wersja metody void f(A x) odziedziczone A

2

obiekt klasy B ma zarówno f(A) i f(B). Kiedy dzwonisz pod numer f(x), zazwyczaj wybierany jest najbardziej szczegółowy , który pasuje do typu x. W tym celu liczy się rodzaj odniesienia.

Więc twój a jest A, dlatego wywołuje f(A). Twój b jest B, dlatego wywołuje f(B). Ale jaki jest twój ab? Typ referencji to A. Tak więc kompilator mówi, aby wywołać przeciążenie f(A).

Ale wtedy, nie powinno to być stosowany przedmiot ab jako A i dlatego drukowany send a fax to A użyciu A.toString() zamiast B.toString()?

Nie, ponieważ wybór metody, która ma zostać wywołana w tym przypadku, nie jest określony przez parametr.To nie jest wybór między przeciążeniami, ponieważ powyższy wybór był, jest wyborem pomiędzy przesłonięcie. Podczas decydowania o tym, która metoda jest używana, typ obiektu z nadklasy lub z podklasy określa ją typ obiektu. Ponieważ przedmiot określony przez ab jest w rzeczywistości B, wybrany jest toString() z.

Więc - wśród przeciążonych sposobów, który jest wybierany jest ustalana na podstawie liczby i rodzaju argumentu oraz rodzaju argument jest typem odniesienia.

Spośród metod zastąpionych, ten, który jest wybrany, jest tym z rzeczywistego typu instancji obiektu, niezależnie od tego, jaki typ odwołania, przez które się on wywołuje.

Należy zauważyć, że metoda jest uznawana za nadrzędną, jeśli ma taką samą nazwę, liczbę parametrów i odpowiednie typy parametrów, co metoda nadrzędna.