Here's a very basic example of what I'm talking about. We have Student, Enrollment, and Club, along with StudentEnrollment and StudentClub representing many-to-many relationships between Students->Enrollment and Students->Club. I am using EFCore for the data model, if that helps.
One basic method of both of these class would be adding a student to an enrollment, or a club, if they are not already a part of that respective object (see StudentEnrollment.AddStudent and StudentClub.AddStudent). The methods are pretty much functionality identical, but the name of the class and the name of the properties you need to compare are different.
Is there a way to create a shared method/class/inheritance/interface/generic/SOMETHING that can be written just once, and used by both classes, despite the different property/class names?
Basic example code (with some pseudocode):
public class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
}
public class Enrollment
{
public int EnrollmentId { get; set; }
public string EnrollmentName { get; set; }
}
public class StudentEnrollment
{
public int EnrollmentId { get; set; }
public int StudentId { get; set; }
public void AddStudent(Student student, Enrollment enrollment)
{
//pseudocode
if (!exists (Where(enrollment.EnrollmentId == this.EnrollmentId && student.StudentId == this.StudentId)))
{
// add student enrollment
}
}
}
public class Club
{
public int ClubId { get; set; }
public string ClubName {get; set;}
}
public class StudentClub
{
public int ClubId { get; set; }
public int StudentId { get; set; }
public void AddStudent(Student student, Club club)
{
//pseudocode
if (!exists (Where(club.ClubId == this.ClubId && student.StudentId == this.StudentId)))
{
// add student club
}
}
}
I don't think inheritance works, nor an interface. Maybe a generic, I'm not very good in that space? Something else?
The question to ask when considering inheritance is whether there is an "is-a" relationship between two classes.
It's pretty obvious that a
StudentClubis not aStudentEnrollment(since enrollment here is class enrollment), nor, vice versa.Is there a common concept that they are both is-a of? You might consider having a
StudentGroupinga common (likely abstract) base class (or perhaps having anIStudentGroupinginterface that they both inherit from).The concept of a StudentGrouping seems way too abstract to spend inheritance on. Is there any reason why you might consider, say, a collection of polymorphic
StudentGroupinginstances on your code.You might might be able to make a case for both classes implementing an
IStudentGroupinginterface (implementingICollection<Student>), which would give a clear indication that both are collections of students (and allow use of the Collection Initialization Pattern).That said, I don't know if that gives you much benefit compared to making both classes simply implement
ICollection<Student>. I suggest just going with that.