2014-09-23 4 views
3

Я хочу сделать автоматическое кастинг просмотров в моем проекте андроида. Итак, я хочу, чтобы переопределитьПереопределение универсальных методов с помощью общего метода

View findViewById(int id) {...} 

метод,

<T extends View> findViewById(int id) {...} 

метода. Но компиляция java не позволяет этого, однако переопределенный метод не конфликтует с родительским и всегда возвращает объект просмотра или его дочерние элементы. Я нашел некоторую информацию, что java не позволяет переопределять не общие методы с помощью общих методов, но объяснение, почему это так, я не могу найти.

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ824 В этом FAQ говорится, что это невозможно, но я не могу понять, почему. В качестве примера мы имеем такие классы:

class Super { 
    public void set(Object arg) { ... } 
    public Object get() { ... } 
} 
class Sub extends Super { 
    public <S extends Number> void set(S arg) { ... } // overloads 
    public <S extends Number> S get() { ... } // overloads 
} 

FAQ говорит, что они должны компилировать с перегрузкой, но у меня есть странная вещь: геттер возвращает ту же ошибку, как мой findViewById, но сеттер компилируется без ошибок.

Может ли кто-нибудь объяснить мне эту вещь? Почему java не позволяет переопределять не общие для общего и почему setter скомпилирован, getter - нет?

Я знаю, что я могу использовать некоторые другой метод, например

<T extends View> findView(int id){ 
    return (T) findViewById(id); 
} 

или

<T extends View> findView(int id, Class<T> clazz) { 
    return clazz.cast(findViewById(id)); 
} 

Но я хочу понять, почему я должен использовать новый метод вместо переопределения?

//1 
@Override 
public View findViewById(int id) { 
    return (View) super.findViewById(id); 
} 
//2 
@Override 
public <T extends View> T findViewById(int id) { 
    return (T) super.findViewById(id); 
} 

Итак, во время компиляции, в чем разница между 1 и 2? Даже метод 1 является более общим, чем 2.

//3 
@Override 
public <T extends View> View findViewById(int id) { 
    return (View) super.findViewById(id); 
} 

После того, как я добавил способ, как описано выше, я наконец понял, что «Т расширяет View» говорит компилятор, что это не тот же метод, как и без «Т распространяется View ». Итак, на самом деле, я создал новый метод, но с тем же именем и параметрами, поэтому он не может компилироваться. Может быть, это не совсем правильно, но, как я понял, нечто похожее на правду.

Спасибо всем, кто пытается мне помочь.

+0

Нет смысла объявлять параметр типа, который вы не используете в сигнатуре. – newacct

+0

Это обвинительно. Я объявил это просто для понимания. Это было после третьего редактирования моего вопроса :) –

ответ

1

set метод в Sub компилируется, потому что вы объявляете метод новый под названием set, который может принять любой аргумент S that extends Number. .Примечание: вы не переопределяете метод set из класса Super в классе Sub, вы перегрузили метод set
С помощью метода get вы выполняете то же самое, что и метод перегрузки get, но на этот раз компилятор жалуется, потому что это неверно, потому что вы изменили просто возвращаемый тип метода. Напр.

public Object get() { 
    return null; 
} 

и вы объявляете другой метод в том же или дочернего класса, изменяя только тип возвращаемого значения метода, как это

public Number get() { 
     return null; 
    } 

тогда компилятор будет жаловаться «метод Get() уже определен», потому что в виде возврата java не является частью сигнатуры метода.
Вы можете повторить ту же самую проблему для set метода, если вы объявляете

public <S extends Number> void set(Object arg) { } 

В этом случае мы опять просто изменить тип возвращаемого значения метода, но чтобы быть действительными параметры метода перегрузки должны быть различными, так

public <S extends Number> void set(String arg) { } // overloads 

будет действительной перегрузкой

+0

Спасибо. Наконец, я понял, что - это что-то затушить параметр, и это другой метод, поэтому он является перегрузкой, а не переопределяющей. Но он имеет одну и ту же подпись, поэтому он не компилируется. –

+0

Приветствую вас, если вы найдете это сообщение полезным, то вы всегда можете повышать – sol4me

+0

Мне нужно 15 баллов репутации :) Но я сделаю это, когда смогу. –

Смежные вопросы