2009-05-18 11 views
7

w "Język programowania Java ™, Fourth Edition" Ken Arnold, James Gosling, David Holmes, jego wspomniano, że:Java Interfejs: dziedziczenie, nadrzędne i przeciążenia Metody

ustęp: (4.3.2) "Podobnie, jeśli interfejs dziedziczy więcej niż jedną metodę z tą samą sygnaturą lub jeśli klasa implementuje różne interfejsy zawierające metodę z tym samym podpisem, istnieje tylko jedna taka metoda. Implementacja tej metody jest ostatecznie zdefiniowana przez klasa implementująca interfejsy i nie ma tam niejasności.Jeśli metody mają ten sam podpis, ale różne typy zwracania, wówczas jeden z typów zwracanych musi być podtypem wszystkich pozostałych, w przeciwnym razie wystąpił błąd podczas kompilacji. Realizacja musi zdefiniować metodę, która zwraca to wspólne podtyp „.

Czy ktoś może dać mi jakiś przykład kodu, który usprawiedliwia punkty powyższym akapicie?

Starałem się napisać kod i sprawdzić, co jest wymienione ale jestem coraz czasie kompilacji błąd sub-interface ukrywa metodę interfejsu podstawa więc może tylko wdrożyć metodę sub-interface.

góry dzięki. -Arun

+0

można wyświetlić kod? –

+1

opublikuj swój kod i swój błąd kompilatora ... daj nam coś, aby (a) powtórzyć problem; i (b) jechać stamtąd. – corlettk

+0

Naprawdę przepraszam - próbowałem przetestować to, co wspomniano w powyższym akapicie, używając j2sdk1.4.2_08 - Nie zdawałem sobie sprawy, że książka jest napisana dla JDK1.5 Oznacza to, że jeśli skompilujesz fragment kodu przez "Daniela Schnellera" używając JDK1.4 otrzymasz "ImplementationOfAandB.java:17: methodB() w ImplementationOfAandB nie może zaimplementować metody B() w InterfaceA; próbuje użyć niekompatybilnego typu" return kompilacji ", podczas gdy z JDK1.5 po prostu działa w porządku. – akjain

Odpowiedz

2

W następujących dwóch interfejsach methodA() jest identycznie zdefiniowany pod względem parametrów (brak) i typu zwracanego (int). Klasa implementacji na dole definiuje pojedynczą metodę z tym dokładnym podpisem. Ponieważ jest zgodny z obydwoma interfejsami, nie ma w tym problemu - wywołania wykonywane przez referencje typu InterfaceA lub InterfaceB będą wysyłane do tej implementacji.

Drugi methodB() definiuje się jako powrót dowolny podtyp Number (lub Number się) w InterfaceA. InterfaceB definiuje methodB() jako zwracającą Integer, która jest podtypem Number. Klasa implementacji faktycznie implementuje metodę z Integer, co jest zgodne z umową zarówno InterfaceA i InterfaceB. Tutaj też nie ma problemu. Skomentowany przypadek methodB() implementowany jako zwracający Double nie zadziałałby jednak: gdy byłby zgodny z kontraktem InterfaceA, byłby on niezgodny z InterfaceB (który wymaga Integer).

Jeśli InterfaceA i InterfaceB również określenie (różne) umowa na methodC() (zakomentowanym w przykładzie) to byłoby sprzeczne i utworzyć błąd kompilatora. Implementacja obu podpisów (różniących się tylko typem zwrotnym) jest niedozwolona w Javie.

Powyższe zasady również byłyby prawdziwe, gdyby dodać jakiekolwiek parametry do metod. Dla uproszczenia trzymałem to z przykładu.

public interface InterfaceA { 
    public int methodA(); 
    public Number methodB(); 
    // public int methodC(); // conflicting return type 
} 

public interface InterfaceB { 
    public int methodA(); 
    public Integer methodB(); 
    // public String methodC(); // conflicting return type 
} 

public class ImplementationOfAandB implements InterfaceA, InterfaceB { 
    public int methodA() { 
     return 0; 
    } 
    public Integer methodB() { 
     return null; 
    } 
    // This would NOT work: 
    // public Double methodB() { 
    //  return null; 
    // } 
} 
+0

Naprawdę mi przykro - próbowałem przetestować to, co wspomniano w powyższym akapicie, używając j2sdk1.4.2_08 - Nie zdawałem sobie sprawy, że książka jest napisana dla JDK1.5 Oznacza to, że jeśli skompilujesz fragment kodu przez "Daniela Schnellera" używając JDK1.4, otrzymasz "ImplementationOfAandB.java:17: methodB() w ImplementationOfAandB nie może zaimplementować metodyB() w InterfaceA; próba użycia niekompatybilnego typu "błąd kompilacji", podczas gdy w JDK1.5 działa poprawnie. – akjain

1
interface A 
{ 
    void foo(); 
    //int bar(); <-- conflicts with B.bar() because of different return type 
} 

interface B 
{ 
    void foo(); 
    //double bar(); <-- conflicts with A.bar() because of different return type 
} 

class C implements A, B 
{ 
    void foo() // this implements A.foo() AND B.foo() 
    { 
     ... 
    } 
} 
8
interface A { 
    void method(); 
    Object returnMethod(); 
} 
interface B { 
    void method(); 
    B returnMethod(); 
} 

class Impl implements A,B 
{ 
    void method() { } 
    B returnMethod() { } 
} 

Jak widać, zarówno A.method()Impl.method() narzędzia i B.method(), natomiast Impl.returnMethod() zwraca się B, który jest dzieckiem Object, spełniając w ten sposób A.returnMethod() „s kontrakt zbyt. Czy te ostatnie wymagałyby typu zwracania, który nie jest rodzicielem typu zwrotu, który byłby błędem comile, ponieważ taka implementacja nie mogłaby istnieć w Impl.

+0

Ale Impl musi zaimplementować obiekt ReturnMethod(), prawda? –

+0

Czy to C#? Pytanie dotyczy języka Java. –

+0

Nie sądzę, że to ma znaczenie w jakim języku;) –

1

Czy to co masz na myśli ?:

interface A { 
    Object get(); 
} 
interface B { 
    Number get(); 
} 

abstract class MyClass implements A, B { 
    // Try to override A.get, but cause a compile error. 
    public Object get() { return null; } 
} 

Taka metoda MojaKlasa jest generowany automatycznie przez javac jako metody syntezy mostu. Musisz wdrożyć pojedynczą metodę zwracającą typ zgodny ze wszystkimi zaimplementowanymi/przesłoniętymi metodami (w tym przypadku Number/Integer/Double/etc).

1
/** 
* This is what you have 
*/ 
interface IXR { 
     //bla-bla-bla 
} 

class CXR implements IXR { 
     //concrete implementation of bla-bla-bla 
} 

interface IX { 
     public IXR f(); 
} 

interface IYR { 
     //some other bla-bla-bla 
} 

class CYR implements IYR { 
     //concrete implementation of the some other bla-bla-bla 
} 

interface IY { 
     public IYR f(); 
} 






/** 
* This is what you need to add 
*/ 
interface IZR extends IXR, IYR { 
     //EMPTY INTERFACE 
} 

class CZXR extends CXR implements IZR { 
     //EMPTY CLASS 
} 

class CZYR extends CYR implements IZR { 
     //EMPTY CLASS 
} 

class CZ implements IX, IY 
{ 
     public static boolean someCondition = true; 

     public IXR implementationOf_X_f() 
     { 
       System.out.println("CXR"); 
       return new CZXR(); 
     } 

     public IYR implementationOf_Y_f() 
     { 
       System.out.println("CYR"); 
       return new CZYR(); 
     } 

     public IZR f() { 
       if (someCondition) { 
         return (IZR) implementationOf_X_f(); 
       } else { 
         return (IZR) implementationOf_Y_f(); 
       } 
     } 

} 






/** 
* This is the usage of the required class 
*/ 
class program 
{ 
     public static void main(String[] x) { 
       CZ o = new CZ(); 
       IZR r = o.f(); 
       if (CZ.someCondition) { 
         CXR xr = (CXR) r; 
         //bla-bla-bla 
       } else { 
         CYR yr = (CYR) r; 
         //bla-bla-bla 
       } 
     } 
} /** 
* This is what you have 
*/ 
interface IXR { 
     //bla-bla-bla 
} 

class CXR implements IXR { 
     //concrete implementation of bla-bla-bla 
} 

interface IX { 
     public IXR f(); 
} 

interface IYR { 
     //some other bla-bla-bla 
} 

class CYR implements IYR { 
     //concrete implementation of the some other bla-bla-bla 
} 

interface IY { 
     public IYR f(); 
} 






/** 
* This is what you need to add 
*/ 
interface IZR extends IXR, IYR { 
     //EMPTY INTERFACE 
} 

class CZXR extends CXR implements IZR { 
     //EMPTY CLASS 
} 

class CZYR extends CYR implements IZR { 
     //EMPTY CLASS 
} 

class CZ implements IX, IY 
{ 
     public static boolean someCondition = true; 

     public IXR implementationOf_X_f() 
     { 
       System.out.println("CXR"); 
       return new CZXR(); 
     } 

     public IYR implementationOf_Y_f() 
     { 
       System.out.println("CYR"); 
       return new CZYR(); 
     } 

     public IZR f() { 
       if (someCondition) { 
         return (IZR) implementationOf_X_f(); 
       } else { 
         return (IZR) implementationOf_Y_f(); 
       } 
     } 

} 






/** 
* This is the usage of the required class 
*/ 
class program 
{ 
     public static void main(String[] x) { 
       CZ o = new CZ(); 
       IZR r = o.f(); 
       if (CZ.someCondition) { 
         CXR xr = (CXR) r; 
         //bla-bla-bla 
       } else { 
         CYR yr = (CYR) r; 
         //bla-bla-bla 
       } 
     } 
} 
+0

Skondensowane odpowiedzi są łatwiejsze do odczytania – davids