2010-10-05 15 views
7

Estoy trabajando con un seguro y tengo dos tipos de pólizas diferentes: el motor y el hogar, representados por dos clases diferentes, Motor y Hogar.C# Clase Herencia

Ambos tienen varios bits de datos en común, por lo que ambos heredarían de otra clase llamada Política. Cuando un usuario inicia sesión en la aplicación, puede tener un motor o una política de hogar, por lo que la aplicación debe mostrar la información genérica y la información exclusiva de Motor o Hogar. Para encapsular todo esto, tengo un objeto de respuesta que tiene tanto un miembro de motor y un miembro del hogar, tal como se muestra a continuación:

public class Response 
{ 
    ... 
    private MotorPolicy     _motorPolicy; 
    private HouseholdPolicy    _householdPolicy; 
    .... 
} 

El código siguiente debe demostrar:

if (response.PolicyType == Enumerations.PolicyType.Motor) 
{ 
    lblDescription.Text = response.MotorPolicy.Description; 
    lblReg.Text = response.MotorPolicy.Reg; 
} 
else 
{ 
    lblDescription.Text = response.HouseholdPolicy.Description; 
    lblContents.Text = response.HouseholdPolicy.Contents; 
} 

El MotorPolicy no lo hace tiene propiedad Contents y HouseholdPolicy no tiene una propiedad Reg.

pero realmente quiero hacer simplemente:

if (response.PolicyType == Enumerations.PolicyType.Motor) 
{ 
    lblDescription.Text = response.Policy.Description; 
    ... 
} 

He intentado usar los genéricos, podría no pudieron encontrar la solución adecuada.

Respuesta

0

definir la interfaz de la política y aplicarla en sus dos las clases de política

Interface IPolicy{ 
    int Reg {get;set;}; 
    string Contents {get;set;}; 
} 

MotorPolicy : Policy,IPolicy { 

string IPolicy.Contents 
    {get;set;}; 


int IPolicy.Reg 
    {get;set;}; 

} 

HouseholdPolicy : Policy , IPolicy { 
string IPolicy.Contents 
    {get;set;}; 


int IPolicy.Reg 
    {get;set;}; 
} 
+2

Tiene una clase base llamada Política, usar una interfaz en cambio no cambiaría nada. – jgauffin

+3

Esa no es la forma en que entiendo bien el diseño de oo. Las políticas domésticas no tienen un número de registro, y las políticas de motor no tienen contenido. Por lo tanto, el diseño es engañoso –

+0

OK ... entonces él puede OP puede definir así de otra manera ... MotorPolicy: Policy, IPolicy – RameshVel

0

La solución más simple sería la implementación de una interfaz con una descripción de la propiedad y una propiedad "contenido", y luego en su política de motor clase, crea una propiedad ficticia de "contenidos" que devuelve "reg".

5

Su respuesta solo necesita un tipo de política, luego puede almacenar un tipo MotorPolicy o HouseholdPolicy en él.

Luego, su respuesta sólo tiene que comprobar si el tipo de datos

if (response.Policy is MotorPolicy) .... 

Alternativamente tienen un método abstracto o una propiedad devuelvan datos de un método abstracto en el tipo de política que está totalmente inplemented por el niño clases y vuelve reg datos o contenidos como apropiados.

+0

Tenga en cuenta que si sigue este camino, puede terminar escribiendo una gran cantidad de instrucciones "if/then" o "switch" para manejar el procesamiento según el tipo. En este caso, querrá considerar un patrón llamado "Reemplazar condicionalmente con Stratgy" http://www.informit.com/articles/article.aspx?p=1398607&seqNum=2 – codekaizen

+0

También podría crear un Dictionary > que asigna cada tipo de política a un método de controlador independiente. – jgauffin

1
public interface IPolicy 
{ 
    string Description { get; } 
    string Reg { get; } 
    string Contents { get; } 
} 

public class MotorPolicy : IPolicy 
{ 
    public string Description 
    { 
     get { return ...; } 
    } 

    public string Reg 
    { 
     get { return ...; } 
    } 

    public string Contents 
    { 
     get { return String.Empty; } 
    } 
} 

public class HousholdPolicy : IPolicy 
{ 
    public string Description 
    { 
     get { return ...; } 
    } 

    public string Reg 
    { 
     get { return String.Empty; } 
    } 

    public string Contents 
    { 
     get { return ...; } 
    } 
} 

public class Response 
{ 
    ... 
    private IPolicy    _policy; 
    .... 
} 

Ahora usted no necesita una enumeración para mostrar el tipo que ha implementado, puede simplemente decir

lblDescription.Text = response.Policy.Description; 
lblReg.Text = response.Policy.Reg; 
lblContents.Text = response.Policy.Contents; 

Editar: Solución alternativa

public interface IPolicy 
{ 
    string Description { get; } 
} 

public interface IHasReg 
{ 
    string Reg { get; } 
} 

public interface IHasContents 
{ 
    string Contents { get; } 
} 

public class MotorPolicy : IPolicy, IHasReg 
{ 
    public string Description 
    { 
     get { return ...; } 
    } 

    public string Reg 
    { 
     get { return ...; } 
    } 
} 

public class HouseholdPolicy : IPolicy, IHasContents 
{ 
    public string Description 
    { 
     get { return ...; } 
    } 

    public string Contents 
    { 
     get { return ...; } 
    } 
} 

public class Response 
{ 
    ... 
    private IPolicy    _policy; 
    .... 
} 

Este hojas con más código en la función de llamada

lblDescription.Text = response.Policy.Description; 
IHasReg hasReg = response.Policy as IHasReg; 
if (hasReg != null) lblReg.Text = hasReg.Reg; 
IHasContents hasContents = response.Policy as IHasContents; 
if (hasContents != null) lblContents.Text = hasContents.Contents; 

pero es considerablemente más extensible que otras opciones presentadas y cumple con su deseo de evitar la funcionalidad en la implementación que no tiene sentido.

+0

Esto es lo que pensé para empezar, pero simplemente no me gustó cómo mi householdPolicy contendría Reg y MotorPolicy contendría Contents. Realmente me gustaría tener un objeto de política que, según los datos obtenidos, tenga solo uno u otro. – Neil

+0

@Chris - Lo miraría al revés. Su respuesta NECESITA una descripción, un registro y los contenidos, por lo tanto, cualquier implementación de la política debe proporcionar esa información, de ahí la interfaz. Las implementaciones concretas devuelven deliberadamente String.Empty en los campos que no se aplican a ese tipo de política. – pdr

0

¿Puede su respuesta contener una MotorPolicy o una HouseholdPolicy o puede contener una de cada?

Si está tratando con uno u otro, cree un tipo base que hereden ambas clases que defina las propiedades comunes.Cuando muestre las propiedades comunes, simplemente copie la Política como el tipo base y úselo.

+0

Contiene tanto una política doméstica como una política motora, pero luego debo referirme incluso a mi descripción como respuesta.MotorPolicy.Description y response.HouseholdPolicy.Description para propiedades comunes. Realmente quiero tener solo response.Policy.Description, así que no estoy a punto de duplicar el código. – Neil

+0

buena respuesta .......... –

0

Mi pensamiento inmediato es ir a por:

public abstract class Response 
{ 
    public abstract Policy Policy {get;}//can be used for stuff for dealing with all policies. 
    public static Response GetResponse(Policy policy) 
    {//factory method 
    if(policy is MotorPolicy) 
     return new MotorResponse((MotorPolicy)policy); 
    if(policy is HouseholdPolicy) 
     return new HouseholdResponse((HouseholdPolicy)policy); 
    throw new ArgumentException("Unexpected policy type"); 
    } 
} 
public class MotorResponse : Response 
{ 
    private readonly MotorPolicy _motorPolicy; 
    public MotorResponse(MotorPolicy policy) 
    { 
    _motorPolicy = policy; 
    } 
    protected override Policy Policy 
    { 
    get { return _motorPolicy; } 
    } 
    // motor specific stuff 
} 
public class HouseholdResponse : Response 
{ 
    private readonly HouseholdPolicy _householdPolicy; 
    public HouseholdResponse(HouseholdPolicy policy) 
    { 
    _householdPolicy = policy; 
    } 
    protected override Policy Policy 
    { 
    get { return _householdPolicy; } 
    } 
    // household specific stuff 
} 
+0

pregunta agradable .............. –

+0

¿Por qué prefiere campos explícitos, etc. en lugar de utilizar una clase base genérica? – Lucero

+0

No, pero no estoy tan familiarizado con los genéricos, especialmente usándolos como clases base, y no pude lograr que esa solución funcionara. ¿¿Sabes cómo?? – Neil

0

me gustaría probar algo como esto:

public class Response 
    { 
    public Policy SelectedPolicy {get;set;} 

    //I don't think you need these, but hard to 
    //say without seeing the rest of the code 
    ... 
    private MotorPolicy     _motorPolicy; 
    private HouseholdPolicy    _householdPolicy; 
    .... 
    } 

continuación

lblDescription.Text = response.SelectedPolicy.Description; 

if (SelectedPolicy is MotorPolicy) 
    lblReg.Text = ((MotorPolicy)response.SelectedPolicy).Reg; 

else if (SelectedPolicy is HouseholdPolicy) 
    lblContents.Text = ((HouseholdPolicy)response.SelectedPolicy).Contents; 

No voy a poner tanto Reg y Contenidos de la clase base o interfaz. Si hago lo que es el propósito de la herencia si todas las clases se ven iguales? Los únicos beneficios que obtendría serían tipos, y eso no me va a ganar mucho en este caso.

5

Cada descendiente de directiva (ahora tiene dos, puede tener más en el futuro, ¿no?) Debe tener sus propios controles de interfaz de usuario que "saben" cómo tratar con la información de política. El mismo enfoque se puede utilizar para otras cosas, como un "controlador" para los objetos de política etc.

La respuesta se puede entonces hacer genérica:

public class Response<T> where T: Policy { 
    ... 
    private T _policy; 
    .... 
} 

Alternativamente, usted podría tener un enfoque más genérico que utiliza la reflexión para mostrar la información, pero estos suelen ser menos "sexys" en cuanto a su apariencia y usabilidad (piense en Property Grid en el diseñador de VS).

+0

Estoy de acuerdo con los controles de UI. – Mike

0

tal vez no entienden la pregunta, pero me acaba de utilizar inheritence

definir la política como

Política public class { cadena pública Descripción {get; establecer;} cadena pública Detalles {get; set;}

} 

public class MotorPolicy:Policy 
{ 
    public void SetReg(string reg) 
    { 
     base.Details = reg; 
    } 
} 

public class HousePolicy:Policy 
{ 
    public void SetContents(string contents) 
    { 
     base.Details = contents; 
    } 
} 

y llamar por

private void Form1_Load(object sender, EventArgs e) 
    { 
     MotorPolicy mp = new MotorPolicy(); 
     mp.Description = "Motor"; 
     SetForm(mp);  
    } 

    private void SetForm(Policy p) 
    { 
     lblDescription.Text = p.Description; 
     lblDetail.Text = p.Details; 

     //then if you still need specifics 
     if (p.GetType() == typeof(MotorPolicy)) 
     { 
      MotorPolicy mp = p as MotorPolicy; 
      //continue assigning mp 
     } 
     else if (p.GetType() == typeof(HousePolicy)) 
     { 
      HousePolicy hp = p as HousePolicy; 
      //continue assigning Hp 
     } 
    } 

Nota puse reg/contenidos como detalle de campo, ya que son los dos tipos de cadenas. Si uno fuera int vs string, tendrían que hacerse por separado.

1

Una opción es añadir un miembro a Policy que sintetiza toda la clase derivada propiedades relevantes para proporcionar un resumen:

public abstract class Policy { 
    public string Description { get; set; } 
    public abstract string Summary { get; } 
} 

public class MotorPolicy: Policy { 
    public override string Summary { 
     get { return this.Description + "\r\n" + this.Reg; } 
    } 
} 

public class HouseholdPolicy: Policy { 
    public override string Summary { 
     get { return this.Description + "\r\n" + this.Contents; } 
    } 
} 

Este centraliza la lógica y hace que el código de la interfaz de usuario sencilla:

label.Description.Text = response.Policy.Summary; 

Esa implementación básica sacrifica la capacidad de formatear las subsecciones por separado. Se podría superar que al exponer el resumen como una colección de cadenas:

public abstract IEnumerable<string> SummarySections { get; } 

Si desea mostrar los detalles de las clases derivadas en formas fundamentalmente diferentes, tendrá a abrazar la lógica condicional en la capa de interfaz de usuario (por ejemplo, puede enumerar los contenidos de la política familiar en una tabla, pero mostrar una imagen escaneada para el registro de la póliza de motor).

1

utilizar el patrón de plantilla:

Crear una llamada política de clase base con un método get abstracta virtual para determinar la descripción de la política.

public abstract class Policy 
{ 
    protected virtual string GetDescription() 
    { 
     return string.Empty()  
    } 

    public string Description 
    { 
     get 
     { 
      return GetDescription(); 
     } 
    } 
} 

public MotorPolicy : Policy 
{ 
    public override string GetDescription() 
    { 
     return ..... ////specific description implementation for MotorPolicy 
    } 
} 

public HouseHoldPolicy : Policy 
{ 
    public override string GetDescription() 
    { 
     return ..... ////specific description implementation for HouseholdPolicy 
    } 
} 


public class Response   
{   
    ...   
    private MotorPolicy     _motorPolicy;   
    private HouseholdPolicy    _householdPolicy; 
    private PolicyType     _policyType;  
    ....   

    public Policy Policy 
    { 
     get 
     { 
      if (_policyType== PolicyType.Motor) 
      { 
       return _motorPolicy; 
      } 
      if (_policyType== PolicyType.Household) 
      { 
       return _householdPolicy; 
      } 

      return null; 
     } 
    }   
}  

código de cliente:

if (response.Policy != null)   
{  
    lblDescription.Text = response.Policy.Description;  
    ...  
}  

Let MotorPolicy y HouseholdPolicy derivan de Política y anulan el método get abstracción de la base y crear una implementación específica de la misma.

En la clase de respuesta solo tiene que obtener la descripción.

0

El suyo es un ejemplo único de "Refactorización del polimorfismo" [Fowler].

Y entonces su método debe aceptar el objeto adecuado y hacer de la siguiente manera:

public void Update(IPolicy policy) 
{ 
     lblDescription.Text = policy.Description; 
     lblReg.Text = .Reg; 

} 
0

Bueno, me gusta las clases abstractas, así que fui con una interfaz de Política

public interface IPolicy 
{ 
    string Description { get; set;} 
    void Display(); 
} 

Luego heredan de crear MotorPolicy

public class MotorPolicy : IPolicy 
{ 
    public string Description { get; set; } 
    public string Reg { get; set; } 

    public void Display() 
    { 
     Console.WriteLine(string.Format("Description: {0}", Description)); 
     Console.WriteLine(string.Format("Reg: {0}", Reg)); 
    } 
} 

Luego, en respuesta, cambié la Política a una lista en la posibilidad de que pueda tener ambas o cualquiera. Ahora hemos descargado el manejo de mostrar los datos a la política específica en sí misma.

public class Response 
{ 
    public List<IPolicy> Policies { get; set; } 

    public void Display() 
    { 
     Policies.ForEach(p => p.Display()); 
    } 

    public void Display(Type t) 
    { 
     var policy = (from p in Policies 
         where p.GetType() == t 
         select p).FirstOrDefault(); 
     policy.Display(); 
    } 
} 

Esto podría cambiarse fácilmente para no utilizar la lista y podemos deshacernos de la pantalla sobrecargada.