2016-04-28 67 views
0
public class StudentDm : EntityBaseDm { 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string FormattedName 
    { 
     get 
     { 
      return LastName + ", " + FirstName; 
     } 
    } 
} 

public class ProviderDm { 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string FormattedName 
    { 
     get 
     { 
      return LastName + ", " + FirstName; 
     } 
    } 
} 

我有一個Student類繼承EntityBaseDm。 我有一個Provider類,我不想繼承EntityBaseDm。當類已經有父類時如何「繼承」方法

我想將FormattedName get方法和實現提取到泛型類中,但是我不想將它放在EntityBaseDm中,因爲它是一般的。我將不得不製作一個接口,如IFirstLastName,但一個接口不允許我實現函數。我知道那裏有很多設計模式,其中一個可以解決這個問題。我想知道是否有人能指點我正確的方向(至少使用正確的模式)

+0

FormattedName是一個屬性,而不是一個函數/方法 –

+0

肯定的,但返回姓氏+「 ,「+ FirstName是一種方法實現。這將比這更復雜,但例如,我簡化了它。將會有10個類將使用這個函數,我想找到一種方法將其提取出來,而不是將它用於所有Dm類。 – andyh0316

回答

2

我同意@ ScottHannen對此的建議。對象組合將會非常合適。

但是,您可以創建您提到的IFirstLastName接口,然後創建一個擴展方法。

public interface IFirstLastName 
{ 
    string FirstName { get; } 
    string LastName { get; } 
} 

public static class IFirstLastNameExtensions 
{ 
    public static string FormattedName(this IFirstLastName fln) 
    { 
     return $"{fln.LastName}, {fln.FirstName}"; 
    } 
} 

public class StudentDm : EntityBaseDm, IFirstLastName 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

public class ProviderDm : IFirstLastName 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

然後,你可以叫上實現IFirstLastName任何一類FormattedName方法:

var dm = new ProviderDm(); 
dm.FormattedName(); 
+0

非常感謝!! ..而斯科特的回答非常好..這一個最適合我的需要,因爲它允許更多的靈活性。例如,我可能會在各個類中爲FirstName設置不同的註釋(例如[Required]或[MaxLength])。而作曲不會讓我這樣做。 – andyh0316

0

答案是abstract class。這與接口類似,您可以爲實現類定義聲明,但您也可以在抽象類本身中定義實現。

例如,你可以有一個抽象NameBase類,像這樣:

public abstract NameBase : EntityBaseDm 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 

    public string FormattedName 
    { 
     get 
     { 
      return LastName + ", " + FirstName; 
     } 
    } 
} 

你的實現類則繼承抽象類:

public class StudentDm : NameBase { 
} 

public class ProviderDm : NameBase { 
} 

注意,你並不需要定義名稱屬性在這些類別中的任一個中,但它們仍然可以使用:

var student = new StudentDm(); 
student.FirstName = "John"; 
student.LastName = "Smith"; 

var fullName = student.FormattedName; // returns Smith, John 
+0

應該指出,他*可能*或*可能不需要*抽象類。很有可能他會想要使用/實例化NameBase來獲得某些東西,而抽象類不允許這樣做。 – Mikanikal

+0

@Mikanikal在他的問題中沒有什麼可以表明這一點,而抽象類滿足他的要求。還要注意,該方法可以標記爲「虛擬」,以允許在實現類中被覆蓋。 – Steve

+0

他的帖子中沒有任何內容可以提出相反的建議。這就是爲什麼我說*可能*或*可能不*。試圖指出「答案是一個抽象類」並不是只有**的答案,他應該理解他所有的選擇。 – Mikanikal

0

您正在尋求多重繼承,而這對於c#來說是不可能的。你的選擇是創建一個從EntityBaseDM繼承的中間類,只實現你想要的方法。您的ProviderDmStudentDm將源自IntermediateBaseDM並提供更多屬性。

class IntermediateBaseDM : EntityBaseDM 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 

    public string FormattedName 
    { 
     get 
     { 
      return LastName + ", " + FirstName; 
     } 
    } 
} 
3

在繼續之前,考慮一下,如果您尚未創建,其中一些對象應該分享另一種方法會發生什麼,但其他人不應該。試圖通過繼承來組合功能可能會突然變得混亂。它不會比它更頻繁地工作。

您可能聽說過「贊成構成而不是繼承」的建議。從廣義上講,它意味着最好將所有東西結合起來提供所需的功能,而不是嘗試實現您需要的功能在基類中的層次結構。

如果一個「名稱」需要格式化等一致的功能,那麼這就是使其成爲自己的類的一個例子。

public class Name 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string FormattedName { get { return LastName + ", " + FirstName; } } 
} 

然後對StudentDm

public Name StudentName { get; set;} 

但是你做一個財產,我不建議把班級因爲一些共享屬性的只是一個層次。遲早(通常更早)出現的東西屬於某些繼承類,但不屬於其他類,然後變得複雜。