2012-05-23 6 views
14

У меня есть интерфейс повреждаемого следующегоJava - прохождение ArrayList типа интерфейса

public interface Damageable { 
    public void handleCollision(float impulse); 
} 

класс, который реализует этот интерфейс, BaseObject

public class BaseObject implements Damageable 

Теперь в третьем классе, у меня есть ArrayList из тип BaseObject

public class ObjectManager {  
    public ArrayList<BaseObject> bodies; 

То, что я пытаюсь сделать, - передать тела ArrayList методу anoth эр класс, который принимает ArrayList

public CollisionManager(ArrayList<Damageable> _bodies) { 
     bodies = _bodies; 
} 

Java не позволяет мне делать новые CollisionManager (тела), где тело имеет типа ArrayList и BaseObject реализует повреждаемую

Я попытался отливка. Говорит, что нельзя использовать от ArrayList<BaseObject> до ArrayList Также попытался использовать Class<? extends Damageable>, но тогда я не могу вызывать методы, объявленные в интерфейсе Damageable. Как передать ArrayList?

+0

Заканчивать этот пост: http://stackoverflow.com/questions/6965035/why-cant-a-method-take-a-collectionsubclass-when-the-methods-signature-is-de – SirPentor

ответ

32

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

public CollisionManager(ArrayList<? extends Damagable> bodies) { 

Кстати, обратите внимание, что я изменил вашу переменную на bodies, а не на _bodies. Подчеркивания не являются частью стандартных соглашений о кодировании Java.


Редактировать в ответ на замечания OP в

Допустим, что вместо интерфейса, вы имели класс бетон под названием Damagable. Сообщая, что компилятор <? extends Damagable> говорит, что он не должен быть экземпляром Damagable. Это okay что тип удлиняетDamagable. В противном случае компилятор предполагает, что у вас есть Damagableточно.

Это не так важно, если вы думаете об Damagable как о интерфейсе, так как нет случая, когда у вас будет экземпляр Damagable. Но они работают по существу одинаково.

Вы должны помнить, что вы работаете с Java типами, а не классами. Синтаксис и структура типа Java менее надежны, чем структура классов.Существует нет концепции implements, когда дело доходит до типов.


Последний раунд правок

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

Так с этими версиями, вы бы:

public CollisionManager(List<? extends Damagable> bodies) { 
+0

Спасибо за ответ, но ArrayList HAS для реализации Damageable, так как я использую методы этого интерфейса. – wirate

+1

'? extends Damagable' * означает * 'реализует Damagable' в Java generic-speak. –

+0

подтвердите пожалуйста. ArrayList означает ArrayList любого типа, который расширяет или реализует интерфейс Damageable right? – wirate

2

Пробег: ArrayList<? extends Damageable > _bodies.

Это говорит о том, что вы хотите, ArrayList состоящий из Class, который проходит (а) инвентарь Damageable

+0

Что такое разница между ArrayList <> и ArrayList ? – wirate

+0

Возможно, я ошибаюсь, но ничего не думаю. Тот, который вы положили, указывает, что он должен быть классом, и продлить/реализовать Damageable, но, конечно же, он должен быть классом (опять-таки я думаю). Тем не менее, это приближается к пределам моего знания. Собирает ли ваш компилятор? –

+0

ArrayList <<Класс > не работает, потому что это не позволит мне вызывать методы, которые были объявлены в интерфейсе. – wirate

2

Другие, несомненно, указывают на технические решения с точки зрения синтаксиса Java.

Я просто хочу отметить несколько вопросов дизайна, которые вы, возможно, следует рассмотреть:

  • Ваш BaseObject реализует повреждаемой. Это означает, что все объекты BaseObject являются повреждаемыми. Почему бы просто не сделать CollisionManager(ArrayList<BaseObject>)? Если вы не собираетесь использовать Damageable в другом месте (т. Е. Есть вещи, которые могут быть повреждены, но не являются базовыми объектами), то это кажется ненужной абстракцией.
  • Обычно для обнаружения столкновений в игре/симуляции вы хотели бы использовать пространственную структуру данных для обнаружения столкновений (например, Octree, Quadtree или AABB tree), а не ArrayList. Поиск коллизий в ArrayList является алгоритмом O (n^2). Это станет большой проблемой, если у вас много живых объектов.
  • Повреждение кажется плохим именем, поскольку функциональность связана с обнаружением столкновений, а не с повреждением - не будет ли Сколидироваться лучше?
+0

+1 Возможно, что-то не в тему, но определенно полезно! –

+0

На самом деле я сделал то, что вы предложили в пункте 1. Я просто опасался. Пункт 2: Box2D обнаруживает столкновения, и мне просто нужно вызвать метод в этом типе при обнаружении столкновения Пункт 3: В моей ситуации есть объекты, которые сталкиваются, но не повреждаются – wirate

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