2011-08-29 6 views
8

Jeśli nie korzystasz z Java Generics, uważam, że nie można mieć dwóch metod w tej samej klasie, które różnią się tylko typem zwracania.Czy można zrobić metodę przeciążania za pomocą generycznych i zmienić tylko ogólny typ podpisu metody?

Innymi słowy, to byłoby nielegalne:

public HappyEmotion foo(T emotion) { 
    // do something 
} 

public SadEmotion foo(T emotion) { 
    // do something else 
} 

jest taka sama prawda, gdy przeciążenia metody, które zwracają typ rodzajowy, które mogą realizować różne interfejsy, takie, jak gdyby dwie następujące metody były obecne w taka sama definicja klasy:

public <T extends Happy> T foo(T emotion) { 
    // do something 
} 

public <T extends Sad> T foo(T emotion) { 
    // do something else 
} 

Czy jest to nielegalne?

+2

Czy próbowałeś go skompilować? Kompilator (zgodny) natychmiast poinformuje Cię, co jest legalne, a co nielegalne. Lepsze pytanie brzmi "dlaczego jest ... nielegalne?" jeśli nie rozumiesz powodów. –

Odpowiedz

5

to jest legalne, ponieważ parametr wejściowy zbyt różni się w zależności od rodzaju ..

Z tego powodu, zgodnie z prawem,

public <T extends Happy> T foo(T emotion) { 
    // do something 
} 

public <T extends Sad> T foo(T emotion) { 
    // do something else 
} 

Ale nie po to,

public <T extends Happy> String foo(T emotion) { 
    // do something 
} 

public <T extends Happy> T foo(T emotion) { 
    // do something else 
} 

Dzięki ...

2

To działało dobrze.

public class Main { 
    public static void main(String[] args){ 
     Main main = new Main(); 
     main.foo("hello"); 
     main.foo(new Integer(5)); 
    } 

    public <T extends String> T foo(T emotion) { 
     return (T) "test"; 
    } 

    public <T extends Integer> T foo(T emotion) { 
     Integer integer = 5; 
     return (T) integer; 
    } 
} 
2

Będzie się kompilował, ale gdy wpadniesz w kłopoty, to czy Happy, czy Sad jest nadklasą drugiej.

Na przykład, następujące kompiluje:

public <T extends Number> T sayHi() { 
    System.out.println("number"); 
    return null; 
} 

public <T extends Integer> T sayHi() { 
    System.out.println("integer"); 
    return null; 
} 

jednak napotkasz problemy przy próbie kompilacji następujące:

Integer test = sayHi(); 

W tym przypadku, po prostu nie można dodać <Integer> do front, ponieważ Integer jest jednocześnie liczbą i liczbą całkowitą.

Jednak dodaje kompiluje

Double test2 = <Double>sayHi(); 

więc w zasadzie tak długo, jak Sad obiektu nie może być instancją Happy przedmiotu i versa wizowego, Twój kod powinien działać tak długo, jak to nazwać z lub przed nazwy metody.

+0

jak napisać dwie metody o tej samej metodzie podpisu, ale o różnych typach zwracanych i powiedzieć, że kompilują, to całkowicie narusza koncepcję przeciążania metod –

1

Jest to zgodne z prawem, jak powiedzieli inni. Chciałbym jednak zwrócić uwagę na to, co dzieje się, gdy typy się przedłużają.

Załóżmy, że mamy dwa interfejsy (działa dla klas, jak również po prostu zmienić podpis):

interface Emotion {} 
interface Happy extends Emotion {} 

i dwie funkcje:

<T extends Emotion> void foo(T obj) {} // Referred as foo1 
<T extends Happy> void foo(T obj) {} // Referred as foo2 

Jeśli obiekt jest zgodny z Emotion JVM wybiorą foo1. Jeśli obiekt jest zgodny z Happy, JVM wybierze foo2, a nie foo1. Zwróć uwagę na kolejność pierwszeństwa. W ten sposób JVM rozwiązuje niejednoznaczność. Jest to jednak poprawne tylko wtedy, gdy parametr ogólny zostanie przekazany jako argument.

Powiązane problemy