2014-01-07 5 views
6

Предположим, что у меня есть класс, моделирующий статьи расходов, называемые Expense. У нас есть расходы на транспортировку, питание и заработную плату. Предположим, что все свойства одинаковы, поэтому существует только один класс Expense с свойством типа. Однако предположим, что я добавляю новый тип расходов, называемый обучением, и для этого требуются новые поля, касающиеся типа обучения, местоположения и даты. Кроме того, существует несколько новых методов, характерных для этого расхода обучения. Поэтому на данный момент мне нужно подклассифицировать класс Expense, чтобы у меня был класс TrainingExpense. Поскольку подкласс теперь определяет тип расходов, делает ли это избыточным свойство «type» в базовом классе Expense? Должен ли я теперь просто подклассифицировать базовый класс Expense для каждого другого типа? Или я должен просто оставить свойство type в базовом классе и иметь его избыточным для любых подклассов?Наследование классов с пустыми подклассами

ответ

6

Вместо наследования я бы использовал композицию здесь. Создайте свойство say ExpenseExtension типа интерфейса IExpenseExtension в базовом классе.

Для типов расходов, которые имеют дополнительные свойства/методы, наследуются от IExpenseExtension и добавляют дополнительные свойства/методы, необходимые. В случае TravelExpense он будет иметь класс TravelExpenseExtension, который наследует от IExpenseExtension дополнительные свойства/методы, которые вам нужны.

В базовом классе создайте соответствующий класс ExpenseExtension на основе свойства ExpenseType.

Использование композиции вместо наследования здесь сделает ее более гибкой.

Я также предлагаю вам создать перечисление со всеми типами и использовать его для свойства ExpenseType.

Проверьте ниже Url, чтобы прочитать о композиции против наследования:

http://lostechies.com/chadmyers/2010/02/13/composition-versus-inheritance/

по ссылке: Отдавая состав объекта над наследованием класса поможет вам сохранить каждый класс инкапсулируется и сосредоточен на одной задаче. Ваши классы и иерархии классов останутся маленькими и будут менее склонны превращаться в неуправляемых монстров.

UPDATE: Смотрите ниже пример кода в C#:

public class Expense 
{ 
    public string Food { get; set; } 

    public ExpenseType Type { get; set; } 

    private IExpenseExtension expenseExtension; 

    public IExpenseExtension ExpenseExtension 
    { 
     get 
     { 
      if(expenseExtension == null) 
      { 
       // Logic to instantiate the correct Extension based on Type property. 
       // You can use Factory design pattern or something like that for this as well. 
      } 

      return expenseExtension; 
     } 
    } 
} 

public interface IExpenseExtension 
{ 

} 

public class TrainingExpenseExtension : IExpenseExtension 
{ 
    public string Location { get; set; } 

    public void GetTrainingDetails() 
    { 

    } 
} 
+0

Thx, мне очень нравится это решение. Но что мне делать с дополнительными методами? – blacktie24

+1

То же самое. Добавьте его в класс ExpenseExtension. Используйте расширение имени вместо полей, поэтому назовите его IExpenseExtension и TravelExpenseExtension. –

+1

Я только что обновил ответ, чтобы сказать «Расширение вместо полей», но вы можете выбрать имя, которое вам нравится. –

1

Другой подход может быть определить интерфейс IExpense, а затем реализовать, так что все ваши «стандартные» модели поведения доступны через интерфейс и специальный поведения через класс. Композиционный подход, как blacktie24, но перевернутый. Все зависит от того, как вы собираетесь получить доступ к дополнительным материалам.

Смежные вопросы