2012-01-03 19 views
7

quiero hacer algo comogenérico con argumentos de tipo variable

public interface Foo<R, P...> { 
    public R bar(P...) {/*misc*/} 
} 

para obtener una matriz de tipos a utilizar en mi aplicación enlazada. ¿Es esto posible en Java?

Varargs está diseñado para permitirme tener cualquier cantidad de argumentos de una clase determinada.

Quiero usarlo (o algo similar) para que mi método acepte varios argumentos, cada uno de los cuales es miembro de una clase diferente dada. Estas clases se definen cuando el genérico está vinculado.

Me doy cuenta de que hay una solución alternativa, pero ¿existe una forma segura de hacerlo?

+0

¿Qué pasa con lo que tienes hasta ahora? El único problema es que varags no juega terriblemente bien con los genéricos. –

Respuesta

7

Ya que al parecer quiere ser capaz de hacer bar tomar múltiples parámetros de tipos diferentes (algo varargs no son utilizados para), sugeriría por lo que es su lugar toma un solo parámetro. A continuación, puede hacer que ese único parámetro sea un contenedor que contenga cada uno de los "parámetros" individuales que desea usar.

En general, sería mejor hacer una clase para cada conjunto de parámetros que desea utilizar con este método para que tenga buenos nombres para cada uno de los objetos que contiene. Sin embargo, también podría hacer algo como crear una serie de tipos de tuplas (como Pair) para usar como titulares.

He aquí un ejemplo:

public class Foo<R, P> { 
    /* 
    * Not sure how you intend to provide any kind of implementation 
    * here since you don't know what R or P are. 
    */ 
    public R bar(P parameters) { ... } 
} 

public class SomeFoo extends Foo<SomeResult, Pair<Baz, Bar>> { 
    public SomeResult bar(Pair<Baz, Bar> parameters) { ... } 
} 

SomeFoo foo = ... 
SomeResult result = foo.bar(Pair.of(baz, bar)); 
+0

Creo que esta es una buena idea, permite que la clase de enlace defina el número y tipo de argumentos, envolviéndolos en un objeto contenedor/tupla. ¿La tupla/par es parte de las bibliotecas centrales/jdk? No pude encontrarlos, aunque me imagino que sería trivial escribir el mío. ¿Sería correcto sugerir que las tuplas en Java cumplen exactamente el rol de las estructuras en c? –

+2

En general, evitaría hacer tipos de tuplas (no existen en el JDK porque simplemente no funcionan bien por varias razones) y crear clases reales que den a cada objeto contenido un nombre útil. La mayoría de las veces lo mencioné porque está cerca de lo que parecías estar solicitando y porque es una opción que tienes. La respuesta corta es que si desea agrupar un número arbitrario de objetos de tipos arbitrarios, una clase es el camino a seguir. Podrías hacer una clase muy pequeña y simple y básicamente actuar como una estructura. – ColinD

+1

Eclipse en realidad tiene una función para hacer esto automáticamente: 'refactor> introducir el objeto de parámetro' – AJMansfield

2

Usted escribió:

quiero usarlo (o algo similar) para que mi método de aceptar varios argumentos, cada uno de los cuales es miembro de un determinado diferente clase.

No creo que sea posible hacer esto de una manera de tipo seguro y sin algunos hacks feo, como incluyendo una instancia de la clase junto con el objeto.

El problema es que con VarArgs en realidad se está pasando en una matriz. Pero no puede tener una matriz con diferentes tipos de objetos, todos tienen que ser iguales (o subclases, entonces si tiene X [] y cada elemento debe ser una subclase de X)

Si su función realmente puede tratar con múltiples tipos, podría crear algo así como una clase que almacena una instancia de Clase junto con una instancia de T, y el pase en una lista variable de ese contenedor.

Así, por ejemplo, usted puede

class TypedInstance<T>{ 
    Class<T> type; 
    T instance; 
} 

y luego tienen una función que se ve algo como

public whatever(TypedInstance<? extends Object>... whatever){ 
    ... 
    doSomethingWith(whatever[0].type, whatever[0].instance); 
    ... 
} 

Se necesitan estos tipos de cortes a causa de tipo borrado de Java. El parámetro genérico se elimina en el tiempo de ejecución, por lo tanto, si desea usarlo, debe volver a colocarlo.

+0

+1 Buena idea, pero la función nunca usa P. No hay seguridad de tipos para los tipos de parámetros que no sean los que tienen para extender Objeto. El tipo de 'instancia' puede ser adquirido por instance.getClass(); básicamente estás envolviendo una instancia de tipo T en un contenedor , lo cual es un poco inútil. –

+0

Cierto, pero no hay una forma real de hacerlo directamente ... aunque la idea de Colin D de usar tuplas anidadas es bastante brillante. Me recuerda la forma en que se hacen las cosas en Scheme/lisp. –

Cuestiones relacionadas