2015-06-01 34 views
7

Zastanawiam się, oprócz różnicy składni, kiedy można użyć ogólnego interfejsu na metodę, która akceptuje ogólny parametr?Java Generic Interface vs Generic Methods, a kiedy używać jednego

public interface Flight<T>{ 
    void fly(T obj); 
} 

nad

public interface Flight{ 
    void <T> fly(T obj); 
} 
+2

chcesz jeden insatnce realizacji 'flight' aby móc obsłużyć w "fly" metoda tylko jeden wybrany typ danych lub dowolnego rodzaju danych? – Pshemo

Odpowiedz

5

Jeśli zadeklarujesz rodzajowe metodę, zawsze niech rozmówcę decydowania, które argumenty typu użyć dla parametrów typu. Implementacja metody musi być w stanie obsłużyć wszystkie możliwe typy argumentów (i nie ma nawet sposobu na zapytanie o rzeczywiste argumenty typu).

Powiedział, że metoda jak <T> void fly(T obj); stwierdza, że ​​rozmówca może używać dowolnego typu dla T natomiast jedyną rzeczą realizacja może polegać na to, że rzeczywisty typ dla T będą przypisane do Object (jak gdyby <T extends Object> została zadeklarowana) .

W tym konkretnym przykładzie nie różni się od deklaracji , która pozwala również na dowolne obiekty.

Natomiast parametr typu na interface jest częścią umowy i mogą być określone lub ograniczone przez realizacji z interface:

public interface Flight<T>{ 
    void fly(T obj); 
} 

pozwala implementacje jak

public class X implements Flight<String> { 
    public void fly(String obj) { 
    } 
} 

ustalanie typu T po stronie implementacji. Lub

public class NumberFlight<N extends Number> implements Flight<N> { 
    public void fly(N obj) { 
    } 
} 

będąc nadal rodzajowy ale ograniczając rodzaj.


Podpis o interface jest również, gdy sam interface jest częścią innej metody, na przykład podpisu

public void foo(Flight<? super String> f) { 
    f.fly("some string value"); 
} 

tutaj, realizacja Flight, które przechodzą do foo, musi być zdolny do spożywania wartość String, więc Flight<String> lub Flight<CharSequence> lub Flight<Object> są wystarczające, ale nie Flight<Integer>. Zgłoszenie takiej umowy wymaga parametrów typu na interface, a nie na metodach interface.

+0

w związku z tym, przy użyciu ogólnego interfejsu podejście w stosunku do metody ogólnej nadal sprowadza się do decyzji projektowej. Ma to sens, dodając typy generyczne do równania tak naprawdę nie zmienia metod i interfejsów, chociaż dodaje pewne funkcje, takie jak ograniczenie typu. 'NumberFlight' może nawet ograniczyć typ bez zmiany umowy pomiędzy' Flight' i ''. To interesujące. Teraz jestem bardziej oświecony, dziękuję bardzo! – yev

0

Należy użyć typu rodzajowego, kiedy można się spodziewać, że większość z tych metod, w implementacji, będzie wykonywać operacje typu dostarczanego podczas tworzenia instancji klasy.

Na przykład ArrayList<E> jest typem ogólnym, ponieważ większość jego operacji (dodawanie, pobieranie, usuwanie itp.) Polega na typie określonym podczas tworzenia.

Metoda ogólna powinna być stosowana, gdy tylko kilka metod w klasie opiera się na różnych typach.

Możesz przeczytać więcej o generycznych w Java Docs.

0

Weźmy na przykład klasę java.util.ArrayList<E>. Podczas tworzenia zmiennych tego typu, trzeba określić typ betonu dla T:

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

Te konkretne typy są używane, gdy wywołanie metody z interfejsu List, że praca z typem T. Wywołując metodę add, można dodawać tylko obiekty String do listy. Pobieranie elementów z listy przy użyciu get, otrzymasz elementy typu betonu String.

W przypadku metod ogólnych typ T jest określony tylko dla tej metody. Bardziej sensowne byłoby, gdyby metody zwróciły wartość tego rodzaju. Często można znaleźć kodu:

MyObject obj = SomeClass.staticGenericMethod(MyObject.class) 

lub

MyObject obj = classInstance.genericMethod(MyObject.class); 

I należy rozpocząć swoją nazwę interfejsu z dużej litery: Flight<T>