2015-07-10 30 views
11

mam trzy klasy:Zagnieżdżony rozciąga się w generycznych

class ClassR {} 
class ClassA<T extends ClassR>{}  
class ClassB<E extends ClassA<T extends ClassR>> extends ClassA<T> { 
    void foo(T param) { 
    } 

    void bar(E param) { 
    } 
} 

Trzecia klasa nie kompiluje chyba zmienię go

class ClassB<E extends ClassA<T>, T extends ClassR> extends ClassA<T> { 
    void foo(T bar) { 
    } 

    void bar(E param) { 
    } 
} 

Czy istnieje sposób, aby zachować tylko parametr E muszę zdać podczas tworzenia ClassB, a T jest wnioskowane? Na przykład, byłoby to wygodne w użyciu:

new ClassB<ClassA<ClassR>>() 

zamiast:

new ClassB<ClassA<ClassR>, ClassR>() 
+0

Side uwaga: lepiej zaimplementować Runnable niż rozszerzyć wątek. – m0skit0

+0

zmieniono na ClassR, ponieważ nie ma znaczenia – Nutel

+1

proszę zaksięguj metodę przy użyciu E – Al1en313

Odpowiedz

0

Nie wiem, czy to jest odpowiedź chcesz, ale na pewno najprostsza wersja brzmi:

class ClassR { 
} 

class ClassA<T extends ClassR> { 
} 

class ClassB<T extends ClassR> extends ClassA<T> { 

    void foo(T bar) { 
    } 
} 

public void test() { 
    ClassB<ClassR> classB = new ClassB<>(); 
} 
+0

Moja zła, używam zarówno E, jak i T w klasie B, czy istnieje sposób, aby nadal mieć E? (zaktualizowałem pytanie) – Nutel

1

To jeszcze prostsze podejście może zadziałać:

class ClassR {} 
class ClassA<T extends ClassR>{}  

class ClassB<T extends ClassR> extends ClassA<T> { 
    void foo(T bar) { 
    } 

    void bar(ClassA<T> param) { 
    } 
} 

i użytkowania następnie omija wszelkie odniesienia do ClassA stać:

class SubR extends ClassR {} 

ClassB<SubR> obj = new ClassB<SubR>(); 
+0

Myślę, że to dobra odpowiedź. Sądząc po pokazanym kodzie, "E" nigdy nie jest zwracane z metody w klasie B. Jednak w ClassB (np. W metodzie "bar") ty (kompilator) wiesz tylko, że jest to coś, co można postrzegać jako ClassA . W związku z tym można powoływać się na mnisi z klasy A i T tylko w sposób bezpieczny. Dlatego nie ma potrzeby wprowadzania parametru typu "E". Jednak jeśli istnieje kod z odwołaniem do instancji klasy B, która wywołuje metody "E", rzeczy naprawdę się różnią. – Sebastian

0

jako typ E rozciąga ClassA można bezpiecznie pominąć parametr ClassA typu w swojej deklaracji.
Właściwy parametr typu ClassA jest wymuszany w drugim parametrze na ClassB.
Zobacz poniżej kod do ilustracji:

class ClassB<E extends ClassA, T extends ClassR> extends ClassA<T> { 

    private ClassA ob; 

    public ClassB(E e, T t) { 
    super(t); 
    ob = e; 
    } 

} 

próba użycia:

class ClassR { 
    public ClassR() {}; 
} 

class ClassS extends ClassR { 
    private int x; 
    public ClassS(int x) { 
    super(); 
    this.x = x; 
    } 
} 

public static void test() { 
    ClassS data1 = new ClassS(1); 
    ClassB <ClassB, ClassS> first = new ClassB<>(null, data1); 
    ClassS data2 = new ClassS(2); 
    ClassB <ClassB, ClassS> second = new ClassB<>(first, data2); 
} 
+0

Dzięki temu rozwiązaniu otrzymasz klasę A jako typ surowy podczas dziedziczenia z klasy A . Ilekroć potrzebujesz informacji o typie ogólnym z ClassA w "E extends ClassA", jesteś zgubiony. Jak stwierdzono powyżej, uważam, że istnieje pewna wada projektowa, która uniemożliwia nam zapewnienie dobrej implementacji, ponieważ pokazany kod pachnie jak ukryte wymagania. – Sebastian

Powiązane problemy