[英]C# Class Inheritance
我正在使用保险,有两种不同的政策类型 - 汽车和家用,由两个不同的类别,汽车和家庭代表。
两者都有几个共同的数据位,因此两者都将从另一个名为Policy的类继承。 当用户登录应用程序时,他们可能有电机或家庭政策,因此应用程序需要显示通用信息以及Motor或Household独有的信息。 为了封装所有这些,我有一个具有Motor成员和Household成员的响应对象,如下所示:
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没有Contents属性,而HouseholdPolicy没有Reg属性。
但我真的想干脆做到:
if (response.PolicyType == Enumerations.PolicyType.Motor)
{
lblDescription.Text = response.Policy.Description;
...
}
我试过使用泛型,找不到合适的解决方案。
您的响应只需要一个Policy类型,然后您可以将MotorPolicy或HouseholdPolicy类型存储到其中。
然后您的响应只需要检查数据类型
if (response.Policy is MotorPolicy) ....
或者,有一个抽象方法或属性从Policy类型的抽象方法返回数据,该方法完全由子类提供,并将reg数据或内容数据作为apporpriate返回。
每个政策后代(现在你有两个,未来可能有更多,对吗?)应该有自己的UI控件,“知道”如何处理政策信息。 同样的方法可以用于其他事情,例如策略对象的“控制器”等。
然后可以使响应变得通用:
public class Response<T> where T: Policy {
...
private T _policy;
....
}
或者,你可以有一个更通用的方法,它使用反射来显示信息,但是它们的外观和可用性通常不那么“性感”(想想VS设计师中的Property Grid)。
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;
但是比其他选项具有更大的可扩展性,并且符合您在实现中避免功能的愿望,这是没有意义的。
一种选择是向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; }
如果要以完全不同的方式显示派生类的详细信息,则必须在用户界面层中包含条件逻辑(例如,您可以在表中列出家庭策略的内容,但显示扫描的图像汽车政策的注册)。
使用模板模式:
使用虚拟抽象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类中,只需获取描述。
定义Policy接口并在两个策略类中实现它
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策略类中创建一个返回“reg”的虚拟“contents”属性。
您的回复是否可以包含MotorPolicy或HouseholdPolicy,还是可以包含其中一个?
如果您正在处理其中一个,那么创建一个基类型,两个类都继承定义公共属性。 输出公共属性时,只需将Policy作为基类型转换并使用它。
我的直接想法是:
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;
....
}
然后
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;
我不会将Reg和Contents都放在基类或接口中。 如果我做的是继承的目的,如果所有类看起来都一样? 我得到的唯一好处就是类型,在这种情况下,这不会让我受益匪浅。
也许我不明白这个问题,但我只会使用继承
将政策定义为
public class Policy {public string Description {get; set;} 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 / contents作为字段详细信息,因为它们都是字符串类型。 如果一个是int vs string,那么它们必须分开完成。
你的是“重构多态性条件”的独特例子[福勒]。
然后你的方法应该接受正确的对象,并执行如下操作:
public void Update(IPolicy policy)
{
lblDescription.Text = policy.Description;
lblReg.Text = .Reg;
}
好吧,我不喜欢抽象类,所以我选择了一个Policy接口
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();
}
}
这可以很容易地改为不使用List,我们可以摆脱重载的显示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.