2010-08-03 8 views
7

Digamos que tiene una interfaz y algunas clases:Java collection paso de los niños como la recolección de los padres

public interface IPanel<ComponentType extends Component> { 
    public void addComponents(Set<ComponentType> components); 
    public ComponentType create(); 
} 

public class Button extends Component { } 

public class LocalizedButton extends Button { } 

public class ButtonsPanel implements IPanel<Button> { 
    public void addComponents(Set<Button> components) { ... /* uses create() */ ; } 
    public Button create() { return new Button(); } 
} 

public class LocalizedButtonsPanel extends ButtonsPanel { 
    public Button create() { return new LocalizedButton(); } 
} 

entonces tengo un conjunto de LocalizedButtons y cuando llamo

final LocalizedButtonsPanel localizedButtonsPanel = new LocalizedButtonsPanel(); 
final Set<LocalizedButton> localizedButtonsSet = new LinkedHashSet<LocalizedButton>(); 
localizedButtonsPanel.addComponents(localizedButtonsSet); 

me sale que este método no es aplicable para estos argumentos. Si trato de sobrecargar este método como addComponents(Set<LocalizedButton> buttons) en LocalizedButtonsPanel, obtengo borrado de tipo, por supuesto.

¿Se puede omitir algún patrón o existe el truco para tratar con esta arquitectura para implementar la adición correcta del conjunto de LocalizedButtons?


tengo la respuesta y yo quiero hacer mi ejemplo más concreto - Tengo algunos validadores en mi aplicación, así que necesito el tipo de colección que también se almacenan como genérico, que se simplifica el código I' ve consiguió usando la respuesta:

public interface IPanel<ComponentType extends Component, CollectionType extends Collection<? extends Component>> extends Validated<CollectionType> { 
    public void addComponents(CollectionType components); 
    public ComponentType create(); 
} 

public class Button extends Component { } 

public class LocalizedButton extends Button { } 

public class ButtonsPanel implements IPanel<Button, Set<? extends Button>> { 
    public void addComponents(Set<? extends Button> components) { ... /* uses create() */ ; } 
    public Button create() { return new Button(); } 
} 

public class LocalizedButtonsPanel extends ButtonsPanel { 
    public Button create() { return new LocalizedButton(); } 
} 

Y en este caso, funciona

+0

existe (puede haber) una pregunta similar http://stackoverflow.com/questions/298305/, pero la respuesta no funciona interfaces Tengo –

Respuesta

6

Cambiar las addComponents() firma a

public void addComponents(Set<? extends Button> components) 

por lo que los métodos acepta conjuntos de subclases de botón. De esta manera, puede pasar un Set<LocalizedButton> como argumento, porque LocalizedButton se extiende a Button y por lo tanto coincide con el parámetro Tipo de Set<? extends Button>.

+0

Oh sí, gracias.Mi estructura era un poco más complicada (lo describiré en la pregunta), pero he corregido mis genéricos para adaptarme a sus consejos y realmente encajan :). –

5

tienes

public class ButtonsPanel implements IPanel<Button> { 
    public void addComponents(Set<Button> components) { ... /* uses create() */ ; } 
    public Button create() { return new Button(); } 
} 

Debe ser

public class ButtonsPanel implements IPanel<Button> { 
    public void addComponents(Set<? extends Button> components) { ... /* uses create() */ ; } 
    public Button create() { return new Button(); } 
} 

La lista se crea sólo para el tipo de botón no para objetos que se extienden ese tipo.

+1

esto: 'public class ButtonsPanel implementa IPanel ' no va a funcionar, porque no se admiten comodines en la sección' implements', y si puedo especificar esto: 'public class GenericButtonsPanel implementa IPanel ' ' continuación LocalizedButtonsPanel extiende GenericButtonsPanel < LocalizedButton> 'en este caso no será el elemento secundario de' ButtonsPanel' que 'extends GenericButtonsPanel

+1

Cierto, edité mi publicación. –

0

Los tipos parametrizados no son covariantes en Java. Esto es bueno, de lo contrario, usted podría agregar un perro a una lista <Cat> que había sido actualizada a la lista <Animal>. Puede agregar covarianza en el sitio de uso, por ejemplo, List <? extends Animal > se le puede asignar una lista <Cat> y no puede llamar a su método add.

Cuestiones relacionadas