To działa :

public interface A {
     A doSomething(); 
}

public interface B extends A{
     B doSomething(); 
}

To nie:

public interface A {
     Collection<A> doSomething(); 
}

public interface B extends A{
     Collection<B> doSomething(); 
}

Czemu? i co mogę zrobić, aby uzyskać funkcjonalność, której chcę w drugim przykładzie?

4
Yossale 17 sierpień 2011, 18:25

3 odpowiedzi

Najlepsza odpowiedź

Zmień to na:

public interface A {
    Collection<? extends A> doSomething();
}

public interface B extends A{
    Collection<B> doSomething(); 
}

I będzie działać poprawnie.

Dzieje się tak, ponieważ „zbiór B” nie rozszerza kolekcji A”, mimo że B rozszerza A. A musi zdefiniować typ zwracany jako „zbiór elementów, które rozciągają się na A”, niż można go bardziej zawęzić jako „kolekcja of B”. Mylące, tak… ale tak właśnie jest.

3
Reverend Gonzo 17 sierpień 2011, 18:29

Powodem jest to, że Collection<B> nie jest podtypem Collection<A>.

Nie każda operacja możliwa z Collection<A> jest również możliwa przy Collection<B>. Przykład: wywołanie add(new A()) działa z Collection<A>, ale musi zawieść z Collection<B> (nawet jeśli jest to sprawdzane w czasie kompilacji).

Jeśli nie zależy Ci na dodawaniu elementów do zwróconych Collection (często zależy Ci tylko na iteracji nad nimi, skutecznie traktując je tak, jakby były tylko do odczytu), możesz to zrobić ten:

public interface A {
     Collection<? extends A> doSomething();
}

public interface B extends A{
     Collection<? extends B> doSomething();
}

Możesz nawet pozwolić B.doSomething() zwrócić Collection<B>, jeśli chcesz, ale wtedy nie będziesz w stanie przedłużyć B ponownie w ten sam sposób.

6
Joachim Sauer 17 sierpień 2011, 18:30

Spróbuj tego

public interface A {
     Collection<? extends A> doSomething(); }

http://www.oracle.com/technetwork/articles/javase/generics-136597.html

0
bpgergo 17 sierpień 2011, 18:30