Можете ли вы перегрузить метод с помощью шаблонов и изменить только общий тип сигнатуры метода? - PullRequest
8 голосов
/ 29 августа 2011

Если вы не используете Java Generics, я считаю, что невозможно иметь два метода в одном классе, которые отличаются только по типу возвращаемого значения.

Другими словами, это будет недопустимо :

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

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

То же самое верно при перегрузке методов, которые возвращают универсальный тип, который может реализовывать различные интерфейсы, такие какесли в одном и том же определении класса присутствуют следующие два метода:

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

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

Это будет незаконно?

Ответы [ 5 ]

5 голосов
/ 29 августа 2011

Это допустимо, поскольку входной параметр также отличается в зависимости от типа.

По этой причине допустимо следующее,

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

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

Но следующее не является

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

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

Спасибо ...

2 голосов
/ 29 августа 2011

Он будет компилироваться, но если вы столкнетесь с проблемами, то если Happy или Sad - суперкласс другого.

Например, следующие компиляции:

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

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

Однако,вы сталкиваетесь с проблемами, когда пытаетесь скомпилировать следующее:

Integer test = sayHi();

В этом случае вы просто не можете добавить <Integer> вперед, потому что Integer по-прежнему является как числом, так и целым числом.

Однако следующие компиляции

Double test2 = <Double>sayHi();

, так что в основном, пока объект Sad не может быть экземпляром объекта Happy, и наоборот, ваш код должен работать, пока вы вызываете его с или впередимени метода.

2 голосов
/ 29 августа 2011

Это бежало просто отлично.

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;
    } 
}
1 голос
/ 09 сентября 2016

Это законно, как говорили другие.Тем не менее, я хочу указать, что происходит, когда типы расширяют друг друга.

Допустим, у нас есть два интерфейса (работает и с классами, просто меняем сигнатуру):

interface Emotion {}
interface Happy extends Emotion {}

И двафункции:

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

Если объект соответствует Emotion, JVM выберет foo1.Если объект соответствует Happy, JVM выберет foo2, а не foo1.Обратите внимание на порядок приоритета.Вот как JVM разрешает неоднозначность.Однако это допустимо только в том случае, если вы передаете универсальный параметр в качестве аргумента.

1 голос
/ 29 августа 2011

Вы можете использовать generic для различения метода в Java.JVM не видит этот тип, однако, если аргумент или тип возвращаемого значения отличаются, он все равно будет компилироваться в компиляторе Sun / Oracle.Это не компилируется для компилятора IBM / eclipse.

Это показывает, что вы хотите, чтобы это происходило на уровне байтового кода.http://vanillajava.blogspot.com/2011/02/with-generics-return-type-is-part-of.html

...