2012-05-23 12 views
14

que tiene una interfaz dañables de la siguiente maneraJava - pasando ArrayList de tipo de interfaz

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

una clase que implementa esta interfaz, BaseObject

public class BaseObject implements Damageable 

Ahora en una tercera clase, tengo un ArrayList de el tipo BaseObject

public class ObjectManager {  
    public ArrayList<BaseObject> bodies; 

Lo que estoy tratando de hacer es pasar los cuerpos de ArrayList a un método de anoth er clase que acepta ArrayList

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

Java no me deja hacer nuevos CollisionManager (cuerpos) donde los cuerpos es de tipo ArrayList y BaseObject implementa dañables

He tratado de fundición. Dice que no puede transmitir desde ArrayList<BaseObject> a ArrayList También intenté usar Class<? extends Damageable> pero luego no puedo llamar a los métodos declarados en la interfaz Daños. ¿Cómo puedo pasar ArrayList?

+0

Salida este post: ¿Cuál es http://stackoverflow.com/questions/6965035/why-cant-a-method-take-a-collectionsubclass-when-the-methods-signature-is-de – SirPentor

Respuesta

32

Tienes que ser explícitos con los genéricos. Por lo tanto, usted tiene que informar al compilador que su tipo genérico no hace han ser un Damagable per se, sino que puede extenderse Damagable:

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

Por cierto, observe que me cambió su variable a bodies en lugar de _bodies. Los subrayados no son parte de las convenciones de codificación Java estándar.


Editar en respuesta a los comentarios de la OP

Digamos que, en lugar de una interfaz, que tenía una clase concreta llamada Damagable. Diciendo al compilador <? extends Damagable> dice que no tiene que ser una instancia de Damagable. Es bien que el tipo extiendeDamagable. De lo contrario, el compilador asume que tiene un Damagableexactamente.

No tiene mucho sentido cuando se piensa en Damagable como interfaz, ya que no hay ningún caso en el que tenga una instancia de Damagable. Pero funcionan esencialmente de la misma manera.

Debe recordar que está trabajando con Java tipos, no clases. La sintaxis y estructura del tipo de Java es menos sólida que su estructura de clase.No hay concepto de implements cuando se trata de tipos.


última ronda de ediciones

Por último, debo señalar que por lo general es mejor utilizar una interfaz para el método de parámetros/constructor y tipos de devolución método. Esto le permite a usted y a quienes usan sus métodos usar cualquier implementación que desee, y le permite cambiar su implementación a su gusto.

Así que con esas revisiones, se tendría:

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

Gracias por la respuesta, pero ArrayList TIENE que implementar Daños ya que estoy usando métodos de esa interfaz. – wirate

+1

'? extends Damagable' * means * 'implementa Damagable' en Java generic-speak. –

+0

déjeme confirmarlo. ArrayList significa una ArrayList de cualquier tipo que extienda o implemente la interfaz Damageable right? – wirate

2

Probar ArrayList<? extends Damageable > _bodies.

Este dice que desea un ArrayList que consiste en una Class que se extiende (así implementos) Damageable

+0

la diferencia entre ArrayList < y ArrayList wirate

+0

Puedo estar equivocado aquí, pero no pienso nada. El que has puesto especifica que debe ser una Clase, y extender/implementar Daños, pero por supuesto tiene que ser una clase de todos modos (de nuevo, creo). Sin embargo, esto se está acercando a los límites de mi conocimiento genérico. ¿Compila uno? –

+0

ArrayList <> no funcionaba porque al hacerlo no me dejaría llamar a los métodos que se han declarado en la interfaz. – wirate

2

Otros, sin duda, señalar las soluciones técnicas desde la perspectiva de la sintaxis de Java.

Sólo voy a mencionar algunos problemas de diseño que tal vez debería considerar:

  • Su BaseObject implementa dañables. Eso significa que todos los objetos Base son Daños. ¿Por qué no hacer un CollisionManager(ArrayList<BaseObject>)? A menos que vaya a utilizar Daños en otra parte (es decir, hay cosas que son Dañadas pero no son BaseObjects), entonces parece una abstracción innecesaria.
  • Por lo general, para la detección de colisiones en un juego/simulación, le conviene usar una estructura de datos espaciales para la detección de colisiones (por ejemplo, Árbol octárbol, Quadtree o AABB) en lugar de una ArrayList. La búsqueda de colisiones en una ArrayList es un algoritmo O (n^2). Esto se convertirá en un gran problema si tienes muchos objetos en vivo.
  • Dañable parece una mala reputación, ya que la funcionalidad se refiere a la detección de colisiones en lugar de al daño: ¿no sería mejor la colisión?
+0

+1 fuera del tema tal vez, ¡pero definitivamente útil! –

+0

De hecho, hice lo que sugeriste en el punto 1. Solo estaba siendo cauteloso. Punto 2: Box2D está detectando colisiones y solo tengo que llamar a un método de este tipo cuando se detecta una colisión Punto 3: Hay objetos en mi situación que colisionan pero nunca se dañan – wirate