2011-07-28 11 views
7

que han estado tratando de generar una fábrica supone para devolver un objeto diferente de una interfaz común (digamos Item) de acuerdo con el parámetro de entrada (lo llamo un contexto) de la función getItem(A context)Polimorfismo y sobrecarga con métodos estáticos en C#.

Ahora, supongamos que defino una nuevo tipo de contexto: B que hereda de A.

Quería devolver un artículo diferente dependiendo de si el objeto pasó a la fábrica era de la clase B o A.

he tratado de hacer de la siguiente manera (la sobrecarga del método):

class Factory 
{ 
    static Item getItem(A context) {...} 
    static Item getItem(B context) {...} 
} 

Esto funciona bien si hago algo como esto:

B bContext=new B(); 
Item it=Factory.getItem(bContext); 

Sin embargo, si yo echo y el objeto con el tipo de A :

A bContext=(A) new B(); 
Item it=Factory.getItem(bContext); 

se llama al primer método de fábrica.

pensé que el polimorfismo se aseguraría la realización del segundo método, incluso después del reparto, y me gustaría saber si me he perdido algo?

Soy consciente de que podría seguir teniendo un único método y utilizar el operador is para comprobar el tipo de variable, pero pensé que la solución que presenté anteriormente era un poco más elegante.

Respuesta

10

La sobrecarga se decide en tiempo de compilación (aparte de usar tipado dinámico en C# 4) en función del tipo de tiempo de compilación de los argumentos - y en el último fragmento, del tipo en tiempo de compilación del argumento es A , por lo que llama al Factory.getItem(A).

Solo las llamadas a métodos virtuales son polimórficas (utilizando anulando), donde el tipo de tiempo de ejecución real del objeto de destino decide qué implementación desea llamar. Si tiene sentido que A y B tengan un método virtual (anulado en B) que puede llamarse por Factory.getItem para manejar las diferencias, eso es genial ... de lo contrario, quedará atrapado con el tipado dinámico o algo así como is.

1

No se puede lograr lo que está pretendiendo la forma de establecer las cosas en este momento.

Una opción es tener algo de lógica en sus métodos de fábrica que puede distinguir el tipo de argumento. Torpe, no es bonito, pero funciona:

class Factory 
{ 
    static Item getItem(ContextA context) 
    { 
     if (context is ContextB) {...} 
     else {...} 
    } 
} 

Otra opción es hacer que el contexto objetos responsables de crear el objeto.Por ejemplo:

public class ContextA 
{ 
    .... 
    internal virtual Item CreateItem() { //specific creation logic for ContextA } 
} 

public class ContextB: ContextA 
{ 
    .... 
    internal override Item CreateItem() { //specific creation logic for ContextB } 
} 

Y ahora que podría hacer:

class Factory 
{ 
    static Item getItem(ContextA context) 
    { 
     return context.CreateItem(); 
    } 
} 

No se si lo hace lo siguiente:

ContextA context = new ContextB(); 
Item item = Factory.getItem(context) 

ContextB.CreateItem() se llamará.