2010-03-19 12 views
12

¿Es posible (o incluso aconsejable) convertir el elemento recuperado de a para cada enunciado en la declaración misma? Sé que cada elemento en la lista será del tipo <SubType>.Elemento de molde en Java para cada instrucción

I.E .:

List<BaseType> list = DAO.getList(); 
for(<SubType> element : list){ 
    // Cannot convert from element type <BaseType> to <SubType> 
    ... 
} 

en lugar de:

List <BaseType> list = DAO.getList(); 
for(<BaseType> el : list){ 
    <SubType> element = (<SubType>)el; 
    ... 
} 

Respuesta

12

¿Usted realmente saben que cada entrada va a ser un subtipo? El DAO simplemente tiene que cumplir el contrato List<BaseType>, y si está asumiendo una subclase, entonces creo que algo está mal en alguna parte. Tal vez me concentre más en hacer que la interfaz con el DAO sea correcta y hacer que devuelva contractualmente lo que desea.

+0

+1 por decir tan elocuentemente el mecanismo de contrato que deben cumplir las interfaces. – aperkins

+1

Desafortunadamente, el código DAO no es nuestro. Sin embargo, los feeds en el origen de datos son. Subclasificamos (la única subclase de este tipo) ya que queríamos funcionalidad adicional en la clase. Como controlamos la entrada y solo estamos colocando objetos , creo que puedo estar bastante seguro de que el objeto recuperado será uno de . Si controlamos todo el código, estarías 100% correcto. –

+3

@Carl: vale la pena ajustar el DAO en ese momento y proporcionar una interfaz * diferente * que haga lo que usted desee. De lo contrario, tendrás que convertir todo a través de tu base de código (potencialmente, me doy cuenta de que estoy haciendo suposiciones acerca de qué tan ampliamente distribuida está) –

1

Posible, sí! pero dios no lo quiera, ¿por qué? Mis primeros intentos en mi carrera hicieron eso y lo he aprendido. La programación en las interfaces siempre tiene una ventaja. Siempre recibo preguntas de desarrolladores junior sobre el manejo de casos donde solo los subtipos tienen los métodos/funcionalidad requeridos.

Decir Clase de animal con el subtipo de perro que tiene el método ladrar(). Quieren la funcionalidad de ladrido(). El verdadero desafío es que quieren un comportamiento de comunicación animal no ladrar() sino animal hablar(). Entonces, una nueva subclase Cat no requeriría miau(). ¿Qué pasa con esto, entonces: - Mi perro forma un paquete, pero los gatos no lo hacen. El comportamiento del paquete de respuesta() no es propiedad de un solo perro. El paquete es un aspecto diferente, pasa un paquete a todos los objetos y pide a los objetos que se unan al paquete. (Patrón de visitante/patrón de adaptador). Mi clase Wolf puede usar el mismo comportamiento.

Soy rígido al respecto, no, si solo es 1 vez, estoy bien. Si la respuesta es que no estoy seguro, entonces es mejor que juegue seguro trabajando en contratos de interfaz.

12

Por todas las razones expuestas por otros, no deberías hacer esto. Sin embargo, si no se puede cambiar la interfaz, el siguiente es posible:

for (BaseType element : list) { 
    SubType subType = (SubType)element; 
    ... 
} 

Por lo que yo sé, esta es la única manera de hacer esto y permanecer verdaderamente un tipo seguro - es decir, no depender del tipo de borrado para la captura de cualquier problemas, que no necesariamente hará hasta mucho más tarde.

Me doy cuenta de que esto no es EXACTAMENTE lo que estaba buscando, pero sí maneja el molde.

+0

Debo señalar que si PUEDE cambiar la interfaz, SIEMPRE será el Subtipo, DEBERÍA cambiar la interfaz, ya sea a través de una extensión de subclase o simplemente cambiándola. – aperkins

+2

Para estar realmente seguro, podría hacer: if (element instanceof SubType) – VolatileDream

+0

Muy cierto, debería haberlo dicho. – aperkins

0

Si no le gustan las colecciones de Google, puede ajustar la lista con el método transform. En tu caso, será muy eficiente y totalmente compatible. Sin embargo, lo pondría como un método de envoltura como Brian sugirió.

public List<SubType> fromDao () 
{ 
    // Put a comment for maintainer 

    // Lists from DAO always contain SubTypes 
    return 
     Lists.transform(
      DAO.getList(), 
      new Function< BaseType, SubType >() 
      { 
       public SubType apply (final BaseType from) 
       { 
        return (SybType) from; 
       } 
      }; 
} 
9

De hecho, es posible combinar el yeso con el bucle, así:

List<BaseType> list = DAO.getList(); 
for (SubType subType : ((List<SubType>) list)){ 
    ... 
} 

O usted puede utilizar este modelo ligeramente más limpio:

List<SubType> list = (List<SubType>) DAO.getList(); 
for (SubType subType : list){ 
    ... 
} 

Se hará Obtiene una advertencia de lanzamiento desactivada del compilador de Java, a menos que la suprimas. El efecto de la primera forma será efectivamente idéntico al lanzamiento de cada elemento dentro del ciclo. La segunda forma también exigirá que las nuevas adiciones a la lista se ajusten a SubType.

Tenga en cuenta que esto NO funcionará con matrices, ya que las matrices tienen distintos tipos de tiempo de ejecución. En otras palabras, BaseType [] no se puede convertir en SubType []. Puede utilizar la API Arrays para evitar esto, así:

BaseType[] array = DAO.getArray(); 
for (SubType subType : Arrays.<SubType>asList(array)) { 
    ... 
} 
+0

Esos lanzamientos no son legales, aunque puede hacer [algunos trucos] (https://stackoverflow.com/questions/933447/how-do-you-cast-a-list-of-objects-from-one-type- to-another-in-java) para evitarlo (como un lanzamiento intermedio a 'List '.) El [tutorial de Java] (https://docs.oracle.com/javase/tutorial/java/generics/subtyping. html) vinculado desde esa pregunta: "Aunque Integer es un subtipo de Number, List no es un subtipo de List y, de hecho, estos dos tipos no están relacionados. El elemento primario común de List y List es List " –

+0

El segundo ejemplo funcionará si DAO.getList devuelve una lista sin tipo en lugar de la lista . El patrón puede ser útil cuando se trata de una base de código heredada donde no se escribe ninguna de las colecciones. – harperska

Cuestiones relacionadas