2016-04-28 2 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 в общий класс, однако я не хочу помещать его в EntityBaseDm, поскольку он является общим. Мне нужно будет создать интерфейс, такой как IFirstLastName, но интерфейс не позволяет мне реализовывать функции. Я знаю, что есть много шаблонов дизайна, один из которых может решить эти проблемы. Интересно, может ли кто-нибудь указать мне правильное направление (по крайней мере, правильный рисунок для использования)

+0

FormattedName это свойство, а не функция/метод –

+0

да, но возвращение LastName + " , "+ 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; } 
} 

Тогда вы могли бы вызвать метод FormattedName любого класса, который реализует IFirstLastName:

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

Спасибо, много! .. в то время как ответ Скотта очень хорош. Этот вариант мне больше всего подходит, так как он обеспечивает большую гибкость. Например, у меня могут быть разные аннотации (например [Required] или [MaxLength]) для FirstName в разных классах. И композиция не позволит мне это сделать. – 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 и реализует только тот метод, который вы хотите. Ваш ProviderDm или StudentDm будет получен от 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;} 

Однако вы делаете это, я бы не рекомендовал размещая классы в иерархии только из-за несколько общих свойств. Рано или поздно (как правило, раньше) происходит что-то, что принадлежит некоторым унаследованным классам, но не другим, а затем становится сложным.