Общий, определенный с использованием интерфейса вместо класса - PullRequest
0 голосов
/ 21 августа 2011

Как я могу указать, что я хочу, чтобы любой объект, реализующий интерфейс A, был разрешен внутри List безопасным для типов способом? Я хочу иметь возможность вызывать данный метод A для всех объектов, относительно того, какого типа они Class.

public interface A (){}

List<? extends A> myList = new ArrayList<? extends A>();

Я получаю: Cannot instantiate the type ArrayList<? extends A>

Если я оставлю универсальный код на стороне экземпляра, он будет работать нормально, но я должен указать @SuppressWarnings({ "rawtypes", "unchecked" }), чтобы компилятор замалчивал о предупреждениях.

Ответы [ 5 ]

3 голосов
/ 22 августа 2011

Чтобы понять, почему не имеет смысла создавать экземпляр new ArrayList<? extends A>(), на самом деле мы можем эквивалентно создать new ArrayList<B>() с любым произвольным классом или интерфейсом B (даже с тем, который не связан ни с одним из ваших объектов ), который реализует A, и созданный в результате ArrayList может быть безопасно назначен переменной типа ArrayList<? extends A>. Тогда вы можете задаться вопросом, о, это глупо, потому что объекты, которые я хочу поместить в него, не относятся к классу B, так как это может быть одинаковым? Но - это то же самое, потому что вы все равно не можете поместить что-либо в ссылку типа Something<? extends A>. Вот почему не имеет смысла создавать new ArrayList<? extends A>().

Как я могу указать, что я хочу любой объект, который реализует A Интерфейс, который будет разрешен внутри Списка безопасным для типов способом? я хочу иметь возможность вызывать данный метод A над всеми объектами, относительно того, к какому типу класса они относятся.

Это именно то, что ArrayList<A>. Он допускает все экземпляры A (конечно, все объекты, которые реализуют A, являются экземплярами A), и вы можете использовать любые методы A для них. Что-то вроде этого - то, что вы хотите:

List<A> myList = new ArrayList<A>();

Нечто подобное List<? extends A> используется только в тех случаях, когда вы получаете объект List из какого-то другого кода, и вы не знаете (или не заботитесь), каков именно общий параметр, с которым они его создали. (В таком случае вы не можете помещать объекты в список.) Это полностью отличается от вашего случая, когда вы создаете объект списка, поэтому вы решаете и, следовательно, точно знаете, какой универсальный параметр используется.

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

Проблема не связана с привязкой параметра типа к интерфейсу, но вы не можете создать экземпляр параметризованного типа с подстановочным знаком.new ArrayList<? extends A>() или даже new ArrayList<?>() не имеет смысла, потому что вы не говорите компилятору, что на самом деле хранит экземпляр List.new ArrayList<A>() с другой стороны, имело бы смысл.

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

просто List<A> хорошо, это позволяет объектам, которые реализуют A в списке, и что все объекты в списке реализуют A

0 голосов
/ 21 августа 2011

Я думаю, что вы ищете:

List<? super A> myList = new ArrayList<A>();
  1. СписокmyList ... это говорит компилятору, что это список некоторого неопределенного типа, а неопределенный тип расширяет A. Вы не можете поместить любой A в этот список, потому что это может быть неправильный точный тип.Все, что знает компилятор, это то, что любой объект в этом списке должен быть A. Я думаю, что вы хотите Listмой список.Это говорит компилятору, что List имеет неуказанный тип, который расширяет A.Теперь компилятор может позволить мне поместить в список любую букву A.
  2. new ArrayList();просто неправильно.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...