[英]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.