2015-10-18 38 views
5

W tym przykładzie na samouczek strony Java page. Dwa interfejsy definiują tę samą domyślną metodę: startEngine(). Klasa FlyingCar implementuje oba interfejsy i musi zastąpić startEngine() z powodu oczywistego konfliktu.Mylić o słowo kluczowe "super" w tym przykładzie Java

public interface OperateCar { 
    // ... 
    default public int startEngine(EncryptedKey key) { 
     // Implementation 
    } 
} 
public interface FlyCar { 
    // ... 
    default public int startEngine(EncryptedKey key) { 
     // Implementation 
    } 
} 

public class FlyingCar implements OperateCar, FlyCar { 
    // ... 
    public int startEngine(EncryptedKey key) { 
     FlyCar.super.startEngine(key); 
     OperateCar.super.startEngine(key); 
    } 
} 

Nie rozumiem, dlaczego od FlyingCar, super jest używany w odniesieniu do obu wersji startEngine() w OperateCar i FlyCar interfejsów. Jak rozumiem, startEngine() nie został zdefiniowany w żadnej super klasie, dlatego nie powinien być nazywany rezydentem w jednym. Ja też nie widzę żadnego związku między super oraz dwa interfejsy wprowadzone w FlyingCar

+4

' super' samo w sobie oznacza superklasę. 'FlyCar.super' jest nowy w Javie 8 i oznacza implementację w interfejsie' FlyCar'. – immibis

+1

Zobacz http://stackoverflow.com/questions/19976487/exicially-calling-a-default-method-in-java – Eran

+1

Dlaczego nie czytasz tego samouczka zamiast po prostu wyodrębniając przykładowy kod? – Holger

Odpowiedz

5

Jak rozumiem, startEngine() nie zostało zdefiniowane w żadnym super klasy, więc nie powinno być określone jako miejsce zamieszkania w jednym.

Tak, został zdefiniowany. Jest to domyślna implementacja, na przykład:

public interface OperateCar { 
    // ... 
    default public int startEngine(EncryptedKey key) { 
     // Implementation 
    } 
} 

OperateCar.super.startEngine(key) wykona wdrożenie domyślny.

Jeśli nie było wdrożenie domyślny, tylko metoda interfejsu następnie stwierdzenie, że nie ma sensu, jako że interfejs nie będzie zawierać implementację coś takiego:

public interface OperateCar { 
    // ... 
    int startEngine(EncryptedKey key); 
} 

Nie widzę również żadnego związku między super i dwoma interfejsami zaimplementowanymi w FlyingCar

Nie jestem pewien, co rozumiem pytasz. super to sposób wywoływania implementacji w interfejsie nadrzędnym. Bez super, nie ma po prostu innego sposobu, aby to wyrazić.

+0

Wiem, że istnieje domyślna implementacja, ale czy chodzi o domyślną klasę (super), na której została wykonana ta domyślna implementacja? W ten sposób ma sens logiczny. I jeśli istnieje domyślna super klasa, wtedy mogę teraz zobaczyć relację między tymi dwoma interfejsami i 'super'. –

+2

@okeyxyz: nie ma czegoś takiego jak "domyślna super klasa" i nie jest jasne, dlaczego tak uważasz. 'InterfaceName.super' jest składnią do wywoływania nie abstrakcyjnej metody interfejsu z klasy implementacji. To jest to. Wygląda to tak *, ponieważ projektanci języka Java tak powiedzieli *. Te nie abstrakcyjne metody interfejsu są nazywane metodami "domyślnymi", ponieważ wymagają oznaczenia tego słowa kluczowego jako nie abstrakcyjne. Jest to zgodne z poprzednimi wersjami językowymi, w których "abstract" jest implikowane, nawet jeśli nie jest określone * i *, ponieważ projektanci języka Java tak twierdzą. – Holger

5

Gdy masz klasę implementującą wiele interfejsów, a te interfejsy zawierają metody z podobnym podpisem metody (np. Dla Twojej metody startEngine).

Aby dowiedzieć się, która metoda do którego się odnosimy, robisz:

yourInterface.super.method(); 

Można przyjrzeć się tym link który odnosi się również pytanie.

Tak, można też to zrobić:

public class FlyingCar implements FlyCar, OperateCar{ 
    public int startEngine(EncryptedKey key) { 
     return FlyCar.super.startEngine(key); 
    } 
} 

albo to:

public class FlyingCar implements FlyCar, OperateCar{ 
    public int startEngine(EncryptedKey key) { 
     return Operate.super.startEngine(key); 
    } 
} 

Tak czy inaczej, trzeba określić interfejs jesteś wywołanie metody z, jeśli jesteś po prostu dzwoniąc metoda z interfejsu.

Jednak ta konkretna sytuacja jest przykładem bez powodu. Najprawdopodobniej wystąpi coś podobnego:

public int startEngine(EncryptedKey key) { 
    // Custom implemenation... 
} 

Który jest ważny. Jednakże, jeśli masz dwa interfejsy z metody, która ma identyczną sygnaturę, która może być również sytuacji, w której trzeba mieć pojedynczy interfejs nadrzędny, który deklaruje, że metody i dwa interfejsy podrzędne, które je przedłużyć:

public interface Car { 
    // ... 
    default public int startEngine(EncryptedKey key) { 
     // Default implementation 
}; 
} 

public interface FlyCar extends Car { 
    // Methods unique to FlyCar 
} 

public interface OperateCar extends Car { 
    // methods unique to OperateCar 
} 
+4

** Reamrks: ** Zwróć uwagę, że domyślny modyfikator *** jest dostępny tylko w Java 8 i nowszych. – user3437460