2010-04-20 4 views
5

Actualmente estoy desarrollando un marco de simulación de peso ligero y de propósito general. El objetivo es permitir que las personas subclasifiquen los objetos de simulación y escenario para sus necesidades específicas de dominio. Los genéricos parecían una forma apropiada de lograr esto, pero me temo que podría estar sumergiéndome en el infierno de los genéricos.Infierno de genéricos de Java - Pasando en esto, pero quiere tipo T

El objeto Sim proporciona acceso a las entidades de simulación y controla el SIM (inicio/pausa/parada)

El objeto Scenario permite rellenar el Sim con entidades de simulación.

Sim:

public class Sim 
{ 
    public <T extends Sim> void loadScenario(Scenario<T> scenario) 
    { 
     reset(); 
     scenario.load(this); 
    } 
} 

Escenario:

public interface Scenario<T extends Sim> 
{ 
    public void load(T sim); 
} 

El objetivo es permitir a los usuarios crear una MySim que extends Sim y una MyScenario que implements Scenario<MySim> para su dominio.

p. Ej. MyScenario:

public class MyScenario<MySim> 
{ 
    public void load(MySim sim) 
    { 
     // make calls to sim.addMySimEntity(...) 
    } 
} 

Específicamente, utilizando el código anterior, la llamada scenario.load(this) en Sim.loadScenario me da el error: El método load (T) en el Escenario de tipo no es aplicable para los argumentos (SIM). Entiendo que esto es porque estoy cargando this (que es del tipo Sim) cuando lo que se requiere es T extends Sim lo que significa que de alguna manera debería pasar un objeto que puede ser cualquier subtipo de Sim.

¿Cuál es la forma de rectificar este problema para lograr lo que quiero lograr? O, ¿es posible? Quizás los genéricos no pueden hacer esto por mí.

+0

Creo que esto puede estar relacionado con una pregunta que hice sobre referencias genéricas circulares: http://stackoverflow.com/questions/2567595/creating-circular-generic-references –

Respuesta

6

Si siempre va a ser un subtipo de Sim, ¿por qué no solo especificarlo en su método y terminarlo? No parece que los genéricos te compren mucho aquí.

Pero de todos modos, creo que quiere loadScenario a ser:

public void loadScenario(Scenario<? extends Sim> scenario) 

EDIT: Bueno, ahora hecho pensé en ello, eso no funcionará bien. Su loadScenario recibirá un escenario con un parámetro de tipo T que es un subtipo de Sim. Pero estás tratando de pasarle un Sim que no tiene garantías de ser el subtipo correcto de Sim.

La solución es que el método Scenario.load necesita tomar un Sim a saber:

public interface Scenario<T extends Sim> 
{ 
    public void load(Sim sim); 
} 

y Sim se mantiene la forma en que lo escribió. Tenga en cuenta que su clase MySim debe implementar esto y explicitamente restringirlo a su parámetro de tipo.

EDIT: Otro enfoque es utilizar un método estático en su clase base Sim:

public class Sim 
{ 
    public static <T extends Sim> void loadScenario(Scenario<T> scenario, T sim) 
    { 
     scenario.load(sim); 
    } 
} 

No obstante es posible hacer de este un método de instancia, ya que pasa una instancia de Sim a algo de tipo T extiende Sim no es seguro. Al hacer un método estático que también pase el Sim, le da al compilador la oportunidad de verificar que el parámetro T para el tipo de escenario y la T para el sim coinciden.

+0

Seguramente quiere decir 'load (T sim)' in el último caso? De lo contrario, el parámetro genérico de la clase es menos que útil ... :-) –

+0

@Andrzej No, creo que quiso decir load (Sim sim). De hecho, el genérico en la clase ya no es útil. Se siente como si no fuera capaz de lograr lo que me gustaría hacer. – Brad

+0

@Andrzej y @Brad. Correcto, el genérico no es tan útil, que era el punto de la primera parte del comentario :-) El polimorfismo normal debería ser tan efectivo aquí. –

2

I understand this is because I'm loading this (which is of type Sim) when what is required is T extends Sim which means somehow I should be passing in an object that can be any subtype of Sim.

No. El problema es que accoding a la especificación de método, debe estar pasando un objeto de clase T, que es la subclase específica de Sim que coincidan con su escenario - el cual this no es (al menos eso el código no puede garantizar que sea).

No estoy seguro de cómo solucionar esto.

Cuestiones relacionadas