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