Как мне абстрагировать коллекцию объектов, принадлежащих другому объекту? - PullRequest
4 голосов
/ 06 ноября 2011

В системе управления профессиональным обучением у меня есть абстрактный класс CourseBase, который я решил использовать в пользу интерфейса ICourse, потому что я предпочел бы избегать дублирования кода реализации для всех классов, полученных из гипотетического, база Course сущность.Каждый курс имеет список предметов, с любым предметом, определенным абстрактным классом SubjectBase.Итак, у меня есть, например,

public abstract class CourseBase : BaseObject
{
    public IEnumerable<SubjectBase> Subjects
    {
        get { return new List<SubjectBase>(); }
    }   
}

public abstract class SubjectBase
{
    public string Name { get; set; }
    public string Description { get; set; }
    public int ValidityPeriod { get; set; }
}

Теперь я хочу добавить конкретный класс LocalCourse, который содержит коллекцию LocalCourseSubject объектов, но потому что я не использую интерфейс для CourseBaseЯ теряю ковариацию, и мне нужно скрыть свойство Subjects абстрактной базы с моим новым:

public class LocalCourse: CourseBase
{
    public IEnumerable<LocalCourseSubject> Subjects
    {
        get { throw new NotImplementedException(); }
    }
}

Я уверен, что я упускаю что-то очень очевидное здесь с точки зрения ОО, но единственные решения, которые я вижу, это:

  1. Полностью исключить объекты из абстрактной базы и добавить только типизированное свойство коллекции в производные классы.ISubjectCollectionOwner в абстрактной базе, а также в конкретных классах.

Прошу извинить меня за тусклость, я уже давно не сталкивался с такой проблемой дизайна.

Ответы [ 2 ]

2 голосов
/ 06 ноября 2011

Почему бы просто не ввести универсальный интерфейс для абстракции курса?Извините, если я пропустил что-то очевидное

public interface ICourse<TSubject>
{
   IEnumerable<TSubject> Subjects { get; }
}

public abstract class CourseBase<TSubject> 
   : BaseObject, 
     ICourse<TSubject>
{
    public IEnumerable<TSubject> Subjects
    {
        get { return new List<TSubject>(); }
    }   
}

public class LocalCourse 
   : CourseBase<LocalCourseSubject>
{
}

Если тема является важной частью сущности курса, вы должны хранить ее как в ICourse, так и в CourseBase, в противном случае я бы предложил абстрагировать ее с помощью интерфейса ISubjectAware

1 голос
/ 07 ноября 2011

Не могли бы вы просто сделать это:

public abstract class CourseBase<T> where T : SubjectBase
{
    public virtual IEnumerable<T> Subjects
    {
        get { return new List<T>(); }
    }
}

public abstract class SubjectBase
{
    public string Name { get; set; }
    public string Description { get; set; }
    public int ValidityPeriod { get; set; }
}

public class LocalCourse : CourseBase<LocalCourseSubject>
{
    public override IEnumerable<LocalCourseSubject> Subjects
    {
        get { throw new NotImplementedException(); }
    }
}

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

...