I want to ask a question about how you would approach a simple object-oriented design problem. I have a few ideas of my own about what the best way of tackling this scenario, but I would be interested in hearing some opinions from the Stack Overflow community. Links to relevant online articles are also appreciated. I'm using C#, but the question is not language specific.
Suppose I am writing a video store application whose database has a Person table, with PersonId, Name, DateOfBirth and Address fields. It also has a Staff table, which has a link to a PersonId, and a Customer table which also links to PersonId.
A simple object oriented approach would be to say that a Customer "is a" Person and therefore create classes a bit like this:
class Person {
    public int PersonId { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }
}
class Customer : Person {
    public int CustomerId { get; set; }
    public DateTime JoinedDate { get; set; }
}
class Staff : Person {
    public int StaffId { get; set; }
    public string JobTitle { get; set; }
}
Now we can write a function say to send emails to all customers:
static void SendEmailToCustomers(IEnumerable<Person> everyone) { 
    foreach(Person p in everyone)
        if(p is Customer)
            SendEmail(p);
}
This system works fine until we have someone who is both a customer and a member of staff. Assuming that we don't really want our everyone list to have the same person in twice, once as a Customer and once as a Staff, do we make an arbitrary choice between:
class StaffCustomer : Customer { ...
and
class StaffCustomer : Staff { ...
Obviously only the first of these two would not break the SendEmailToCustomers function.
So what would you do?
- Make the Personclass have optional references to aStaffDetailsandCustomerDetailsclass?
- Create a new class that contained a Person, plus optionalStaffDetailsandCustomerDetails?
- Make everything an interface (e.g. IPerson,IStaff,ICustomer) and create three classes that implemented the appropriate interfaces?
- Take another completely different approach?
 
     
     
     
     
     
     
     
     
     
     
    