Generyki w interface - dziedzicznie

0

Hej
Jest sobie interface

public interface ScheduledFuture<V> extends Delayed, Future<V>

Delayed

public interface Delayed extends Comparable<Delayed>

czyli wydawałoby się że robiąc swoją implementacje ScheduledFuture powinna wyglądać (z pominięciem reszty metod)

class Foo implements ScheduledFuture {
@Override
public int compareTo(Delayed delayed){
   return -1;
}
//Reszta metod nie jest tu istotna
}

No i IntelIij tak wygenerował i nie podkreśla jako błąd, ale przy kompilacji dostaję 

Foo is not abstract and does not override abstract method compareTo(java.lang.Object) in java.lang.Comparable

Co, dlaczego i jak?

1
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class Test {

    public interface ScheduledFuture<V> extends Delayed, Future<V> {}
    public interface Delayed extends Comparable<Delayed> {}

    class Foo implements ScheduledFuture<String> {

        public int compareTo(Delayed o) {
            return 0;
        }

        public boolean cancel(boolean mayInterruptIfRunning) {
            return false;
        }

        public boolean isCancelled() {
            return false;
        }

        public boolean isDone() {
            return false;
        }

        public String get() throws InterruptedException, ExecutionException {
            return null;
        }

        public String get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
            return null;
        }

    }

    public static void main(String[] args) {
        System.out.println("HI");
    }
}

ScheduledFuture rozszerza wiecej niz jeden interfejs, w szczegolnosci rozszerza Future, wiec musialbys tez zaimplementowac metody z tego interfejsu jak chcesz zrobic klase ktora implementuje interfejs ScheduledFuture.

edit:
class Foo implements ScheduledFuture**<String>** <----- tego brakuje : <String>

0

Nie tu jest błąd i miałem na myśli pominięcie reszty metod pisząc w nawiasie (z pominięciem reszty), poprawie zaraz w poście

0

dobra, blad masz przez to, ze klasa rozszarzajaca generyczny interfejs ScheduledFuture nie podaje jakiego typu jest type-argument <v>. Szczerze mowiac nie wiem czemu taki jest blad, podejrzewam ze implicite kompilator zaklada ze wtedy wszystkie interfejsy, nawet tranzytywne z automatu fallbakuje sie do Object.

Faktycznie, dzięki

0

hmm, dalej nie wiem czemu. A jestem ciekaw.

Do zreprodukowania przez:

public interface Delayed<T> extends Comparable<Delayed> {
}

class Foo implements Delayed {

    public int compareTo(Delayed o) {
        return 0;
    }
}

EDIT:
(w celu rozjasnienia oryginalnego problemu)
w snippecie powyzej jest blad, brakuje typu przy implementacji interfejsu.
Pytanie jest takie, dlaczego kompilator pokazuje, ze metoda compareTo w Foo powinna przyjmowac Object? Koniec koncow ten interfejs rozszerze interfejs Comparable<Delayed>, wiec logicznym (gdyby jak zakladam nie type-erasure) bylo by, aby informacja o typie zostala.

Wolam ekspertow.
@jarekr000000 @Wibowit @Shalom

0

A to nie jet tak, że interfejs ScheduledFuture dziedziczy metody z Delayed i Future dlatego klasa Foo musi zaimplementować wszystkie metody? Gdyby Foo było klasą abstrakcyjną to wtedy te metody musiałyby zostać zaimplementowane przez klasy, które ją rozszerzają.

0

Tak, ale nadal nie o to jest pytanie ;) chodzi o to, że bez podania generyka do metody CompareTo chce Object, a po podaniu jakiegokolwiek działa już z Delayed.
Może coś z tego pomoże, ale dopiero czytam https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html

1

Ktoś mnie wywołał. Na szybko - może ten kod miał wyglądać tak :-)

public interface Delayed extends Comparable<Delayed> {
}
 
class Foo implements Delayed {
 
    public int compareTo(Delayed o) {
        return 0;
    }
}

EDIT:

Szukacie tematu o nazwie Bridge methods:
pierwszy link z google:
http://stas-blogspot.blogspot.com/2010/03/java-bridge-methods-explained.html

1

Z tego co czytam dokumentację https://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html to prawdopodobnie przez brak podania niczego jako generyk, zawija sobie wszystko na Object nawet jeśli jawnie jest podany <Delayed>, ale jest on 'niżej'

2

Nie rozumiem pytania. Masz tam rawtype, czyli robisz coś z generykiem ale nie podajesz typu do parametryzacji.
Musisz mieć
class Foo<T> implements Delayed<T> i zacznie to mieć sens. Skoro nie podałeś typu parameryzującego to jest nim Object.

Problem wynika z tego ze Delayed jest tutaj typem generycznym ale potem używasz go jako rawtype. Generyki NIE SĄ ko/kontra-wariante. To znaczy że np. List<String> NIE jest podtypem List<Object>.
Przykład:

List<Object> list = new ArrayList<String>();

To się nie skompiluje. Analogicznie ma sie sprawa z argumentami w klasach dziedzicących w metodach override -> Delayed czy też Delayed<Object> nie jest tym samym co Delayed<T>.

0

@Shalom:
Odpowiadasz sensownie ale mam wrażenie, że trochę nie o to pytam, albo czegoś nie rozumiem. Mając coś takiego:

    public interface ScheduledFuture<V> extends Delayed, Future<V> {}
    public interface Delayed extends Comparable<Delayed> {}

Czym się różni w tym przypadku implements ScheduledFuture od implements ScheduledFuture<Object>?

1

@danek różni sie tym:

List<String> stringi = new ArrayList<>();
List rawtype = stringi; //ok
List<?> wildcard = stringi; //ok
List<Object> obiekty = stringi; //nie ok

Jak widzisz to nie jest to samo ;]
Rzuć też okiem na https://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html

1 użytkowników online, w tym zalogowanych: 0, gości: 1