How should I abstract from a collection of objects belonging to another object?

In the vocational training management system, I have an abstract CourseBase class, which I decided to use in favor of the ICourse interface, because I would rather avoid duplicating the implementation code for all classes derived from the hypothetical, basic Course object. Each course has a list, if subjects, with any subject defined by the abstract SubjectBase class. So, I have, for example.

 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; } } 

Now I want to add a specific LocalCourse class that contains a collection of LocalCourseSubject objects, but since I do not use the interface for CourseBase , I lose covariance and I need to hide the abstract base Subjects property with my new one:

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

I am sure that I am missing something very obvious here from the point of view of OO, but the only solutions that I see are:

  • Completely omit objects from the abstract base and add only the specially typed property of the collection to derived classes.
  • Implement an interface, such as ISubjectCollectionOwner in an abstract database, as well as specific classes.

Please excuse my dullness here, it has been a while since I was happy to encounter a design problem like this.

+4
source share
2 answers

Can't you do it:

 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(); } } } 

I think that in order to achieve your short-term goal, in any case, it is assumed that the overall picture is that each of the CourseBase heirs will have a collection of the same type of subject-subject. But, if it is, it looks like a parallel inheritance hierarchy, which can sometimes be the smell of code (not to mention that it is mandatory - I don't know all the details of the area you are modeling).

+1
source

Why not just introduce a common interface for the abstract course? Sorry if I missed something obvious.

 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> { } 

If the Theme is an important part of the essence of the course, you must save it both in the ICourse course and in CourseBase, otherwise I would prefer to abstract it using the ISubjectAware interface

+2
source

Source: https://habr.com/ru/post/1379853/


All Articles