2010-10-05 134 views
7

我正在与保险合作,并有两种不同的政策类型 - 汽车和家庭,由两个不同类别Motor和Household代表。C#类继承

两者都有几个共同的数据位,所以两者都会从另一个称为Policy的类继承。当用户登录应用程序时,他们可能会有电机或家庭政策,所以应用程序需要显示通用信息和汽车或家庭特有的信息。来封装这一切,我有既具有电动机构件和家庭成员的响应对象,如下所示:

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

下面的代码应证明:

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; 
} 

的MotorPolicy不具有内容属性并且HouseholdPolicy没有Reg属性。

但我真的想简单地做:

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

我已经使用泛型尝试,也没找到合适的解决方案。

回答

0

定义策略界面并在两个策略类

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

他有一个名为Policy的基类,使用接口而不会改变任何东西。 – jgauffin 2010-10-05 14:25:54

+3

这实际上并不是我如何理解优秀的oo设计。家庭政策没有注册号码,汽车政策没有内容。因此,设计是误导 – 2010-10-05 14:28:20

+0

行..然后他可以OP可以这样定义另一种方式.. MotorPolicy:Policy,IPolicy – RameshVel 2010-10-05 14:29:09

0

实现它的最简单的解决办法是实现一个具有描述性和“内容”属性的接口,然后在您的汽车政策类,创建一个返回“reg”的虚拟“内容”属性。

5

您的回复只需要一个策略类型,然后可以在其中存储MotorPolicy或HouseholdPolicy类型。

那么你的回应只需要检查数据类型

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

或者有一个抽象方法或策略类型的抽象方法由子类和回报章充分inplemented返回数据的属性数据或内容数据为apporpriate。

+0

请注意,如果您追求这条路径,您最终可能会编写大量“if/then”或“switch”语句来处理基于类型的处理。在这种情况下,您需要考虑一种名为“用条件替换条件”的模式http://www.informit.com/articles/article.aspx?p=1398607&seqNum=2 – codekaizen 2010-10-05 14:32:09

+0

他也可以创建一个Dictionary >它将每个策略类型映射到一个单独的处理程序方法。 – jgauffin 2010-10-05 14:48:39

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; 
    .... 
} 

现在你不需要一个枚举显示哪些类型你已经实现了,你就可以说

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

编辑:另一种解决方案

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; 
    .... 
} 

这叶子你在调用函数中有更多的代码

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; 

但是比其他选项更具可扩展性,并符合您在实现中避免功能无效的需求。

+0

这就是我以为开始,但只是不喜欢我的householdPolicy如何包含Reg,并且MotorPolicy将包含内容。我们真的希望有一个政策对象,根据所获得的数据,只有一个或另一个。 – Neil 2010-10-05 14:36:18

+0

@Chris--我会用另一种方式来看待。您的回应需要描述,注册和内容,因此任何政策实施都应提供该数据,因此也是界面。具体实现故意在不适用于该类型策略的字段中返回String.Empty。 – pdr 2010-10-05 15:21:37

0

您的回答可以包含MotorPolicy或HouseholdPolicy,还是可以包含其中的一个?

如果您正在处理其中一个或另一个,则创建两个类都继承的基类型,该类型定义了常用属性。当您输出公共属性时,只需将策略转换为基本类型并使用它。

+0

它确实同时包含一个HouseholdPolicy和一个MotorPolicy,但我必须参考甚至我的描述作为response.MotorPolicy.Description和response.HouseholdPolicy.Description的常见属性。我真的想只是有response.Policy.Description,所以我几乎不复制代码。 – Neil 2010-10-05 14:38:08

+0

不错的答案.......... – 2010-10-05 14:57:19

0

我立即想到的是去:

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

不错的问题.............. – 2010-10-05 14:42:49

+0

为什么你喜欢显式字段等,而不是使用泛型基类? – Lucero 2010-10-05 14:46:04

+0

我不这样做,但我并不熟悉泛型,特别是将它们用作基类,而且我无法获得解决方案。你知不知道怎么?? – Neil 2010-10-05 14:49:24

0

我会尝试这样的事:

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; 
    .... 
    } 

然后

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; 

我不会把两个注册及内容基类或接口。如果我做了什么是继承的目的,如果所有的类看起来都一样?我得到的唯一好处就是类型,在这种情况下这不会让我受益匪浅。

5

每个Policy后裔(现在你有两个,你将来可能会有更多,对吗?)应该有他们自己的UI控件,它们“知道”如何处理策略信息。同样的方法也可以用于其他的东西,如“控制器”的政策目标等

响应,然后可以制作一般:

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

或者,你可以有一个更通用的做法,使用反射来显示信息,但它们的外观和可用性通常不那么“性感”(想想VS设计器中的属性网格)。

+0

我同意UI控件。 – Mike 2010-10-05 14:56:12

0

也许我不明白的问题,但我只想用的传承

定义政策

公共类政策 { 公共字符串描述{获得;设置;} public string Details {get;设置;}

} 

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

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

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 
     } 
    } 

注意我把REG /内容作为现场细节,因为它们都是字符串类型的呼叫。如果一个是int和string,那么他们必须分开来完成。

1

一种选择是将成员添加到Policy,其合成的所有派生类的相关属性提供的摘要:

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; } 
    } 
} 

此集中了逻辑和使用户接口代码简单:

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

该基本实现牺牲了分开设置小节格式的能力。你可以克服通过暴露总结作为字符串的集合:

public abstract IEnumerable<string> SummarySections { get; } 

如果你想显示的派生类的根本不同的方式的细节,你必须拥抱在用户界面层的条件逻辑(例如,您可以将家庭政策的内容列入表中,但会显示马达政策注册的扫描图像)。

1

使用模板模式:

与虚拟抽象get方法创建一个基类叫做政策,以确定政策的说明。

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; 
     } 
    }   
}  

客户端代码:

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

让MotorPolicy和HouseholdPolicy从政策中获得,并覆盖从基础的抽象get方法,并创建一个具体的实现它。

在Response类中获取描述。

0

你是“重构多态性条件”[Fowler]的独特示例。

然后你的方法应该接受适当的对象,如下操作:

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

} 
0

好吧,我不喜欢抽象类,所以我与政策的接口

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

然后我们继承去它创建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)); 
    } 
} 

然后为了响应我改变了政策到一个列表中的机会,你可以有两个或两个。现在我们已经卸载了将数据显示给特定政策本身的处理。

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(); 
    } 
} 

这可以很容易地更改为不使用列表,我们可以摆脱重载显示。