Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#类继承_C#_.net_Generics_Inheritance - Fatal编程技术网

C#类继承

C#类继承,c#,.net,generics,inheritance,C#,.net,Generics,Inheritance,我从事保险工作,有两种不同的保单类型-汽车和家用,由两个不同的类别表示,汽车和家用 两者都有几个共同的数据位,因此都将从另一个名为Policy的类继承。当用户登录应用程序时,他们可能有汽车或家庭保险单,因此应用程序需要显示通用信息以及汽车或家庭特有的信息。为了封装所有这些,我有一个response对象,它既有一个Motor成员,也有一个househome成员,如下所示: public class Response { ... private MotorPolicy

我从事保险工作,有两种不同的保单类型-汽车和家用,由两个不同的类别表示,汽车和家用

两者都有几个共同的数据位,因此都将从另一个名为Policy的类继承。当用户登录应用程序时,他们可能有汽车或家庭保险单,因此应用程序需要显示通用信息以及汽车或家庭特有的信息。为了封装所有这些,我有一个response对象,它既有一个Motor成员,也有一个househome成员,如下所示:

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没有Content属性,HouseholdPolicy没有Reg属性

但我真的很想做:

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

我尝试过使用泛型,但找不到正确的解决方案

定义策略接口并在两个策略类中实现它

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

最简单的解决方案是使用description属性和“contents”属性实现一个接口,然后在motor policy类中创建一个返回“reg”的伪“contents”属性。

您的响应只需要一个策略类型,然后您就可以将MotorPolicy或HouseholdPolicy类型存储到其中

然后您的响应只需要检查数据类型

if (response.Policy is MotorPolicy) ....
或者,让一个抽象方法或属性从策略类型上的抽象方法返回数据,该策略类型由子类完全实现,并相应地返回reg数据或内容数据

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;

但是,与提供的其他选项相比,它的可扩展性要高得多,并且符合您避免在实现中使用毫无意义的功能的愿望。

您的响应是否可以包含MotorPolicy或HouseholdPolicy,或者是否可以包含其中一个


如果要处理其中一个,则创建一个基类,该基类由两个类继承,定义公共属性。当您输出公共属性时,只需将策略强制转换为基本类型并使用它。

我的直接想法是:

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
}

我想试试这样的东西:

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

我不会把注册表和内容都放在基类或接口中。如果我这样做了,如果所有类看起来都一样,那么继承的目的是什么?我能得到的唯一好处是类型,在这种情况下,这对我没有多大好处。

每个策略子代(现在有两个,将来可能会有更多,对吧?)都应该有自己的UI控件,“知道”如何处理策略信息。同样的方法也可以用于其他事情,例如策略对象的“控制器”等

然后可以将响应设置为通用:

public class Response<T> where T: Policy {
    ...
    private T _policy;
    ....
}
公共类响应,其中T:Policy{
...
私人信托基金政策;
....
}

或者,您可以使用更通用的方法,使用反射来显示信息,但这些方法在外观和可用性方面通常不那么“性感”(想想VS designer中的属性网格)。

也许我不理解这个问题,但我只会使用继承

将策略定义为

公共阶级政策 { 公共字符串说明{get;set;} 公共字符串详细信息{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;
    }
}
拜访

    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/contents作为字段详细信息,因为它们都是字符串类型。如果其中一个是int vs string,则它们必须分开执行。

一个选项是向
策略添加一个成员,该成员合成所有派生类的相关属性,以提供摘要:

 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; }
public abstract IEnumerable SummarySections{get;}

如果您想以根本不同的方式显示派生类的详细信息,则必须在用户界面层采用条件逻辑(例如,您可以在表格中列出家庭保险单的内容,但显示扫描图像以进行汽车保险单的登记)。

使用模板模式:

使用虚拟抽象get方法创建名为Policy的基类,以确定策略的描述

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从Policy派生并重写基础中的抽象get方法,并创建它的特定实现


在Response类中,只需获取描述。

您的示例是“将条件重构为多态性”[Fowler]

然后,您的方法应接受适当的对象,并执行以下操作:

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

}

嗯,我不喜欢抽象类,所以我使用了一个策略接口

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();
    }
}
公共类响应
{
公共列表策略{get;set;}
公共空间显示()
{
Policies.ForEach(p=>p.Display());
}
公共空白显示(t型)
{
var policy=(来自Policies中的p
其中p.GetType()==t
选择p).FirstOrDefault();
policy.Display();
}
}

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

他有一个名为Policy的基类,使用接口将不会改变任何东西。这并不是我理解好的oo设计的真正原因。家庭政策没有注册号,汽车政策也没有内容。因此,设计是错误的ingOK..然后他就可以了
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();
    }
}