0

I recently had a small "argument" about inheritance with a friend. I think people overuse it a lot. Intuition tells me that that the only good reason for class inheritance is polymorphism - when there is a case that you want to treat uniquely object of different but related classes.

Our argument was about having a BaseEntity class for Entity Framework that only has Id property. My friend says it's good because he can have generic repositories then. W don't agree with him.

  1. Usually there's no such thing as a generic repository, you'll end up with "Refused bequest" smell.
  2. What's the point of treating let's say a user and an invoice uniquely? These are 2 totally different things.

Unfortunately I couldn't make any good points in spite of "it makes no sense". :)

After a while I also realized that I drifted away from inheritance itself and now I tend to use interfaces instead. Actually in my recent web project (quite a big one) I can't recall any inheritance. Now I'm not sure when it is an appropriate technique anymore.

So guys, please help me here.

  1. What do you think about what I wrote?
  2. Can you find any arguments I can use against my friend?
  3. When it really is a good practice to use inheritance? (Please be specific and throw some examples)

Please don't try to explain to me what the inheritance is all about. I'm very familiar with that and I used it a lot. Like I mentioned above, over time I just drifted away from it, because I couldn't find the right usage for it. Simply interfaces seem to be a better approach to me in most cases.

3
  • 3
    Actually polymorphism is not a good reason to use inheritance. Interfaces accomplish polymorphism too, and are less prone to the typical inheritance problems.
    – user7043
    Apr 4, 2014 at 21:35
  • 1
    Voted to close as duplicate because of at least this answer and this answer in suggested duplicate.
    – user53019
    Apr 5, 2014 at 11:56

1 Answer 1

1

Like you, I tend to favor composition over inheritance. However, let me give you an example where I find inheritance works really well...

Let's say you have a screen where you're editing a list of Users. So you have an entity called User which is your persistence object. Then I prefer to present a flattened model of this to my UI for editing, since there's usually extra logic and checks going on:

class User
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
}

interface IEditUser
{
    string Name { get; set; }
    DateTime DateOfBirth { get; set; }
    int Age { get; }
    void CommitChanges();
    void Delete();
}

Now when there's editing going on, we need to load the list of Users with the initial values, let them be edited, and then you can choose whether to Save or Cancel those changes. Since handling a newly created User is much different than handling an existing User (some fields are only edited in one of those situations, the code for persisting them are different, etc.). That's why I like to do this:

abstract class EditUserBase : IEditUser
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public int Age { get { return DateTime.Today.Year - this.DateOfBirth.Year; } }
    public abstract void CommitChanges();
    public abstract void Delete();
}

Then my class for tracking new users added to the list (but not saved to the database):

class EditNewUser : EditUserBase
{
    public EditNewUser()
    {
        this.Name = string.Empty;
        this.DateOfBirth = DateTime.Today;
    }

    public override void CommitChanges()
    {
        var user = new User()
            {
                Name = this.Name,
                DateOfBirth = this.DateOfBirth,
            };
        // persist to database
    }

    public override void Delete() {} // nothing to do
}

...and finally a class for tracking changes to existing entities:

class EditExistingUser : EditUserBase
{
    private readonly User existingUser;

    public EditExistingUser(User existingUser)
    {
        this.existingUser = existingUser;
        this.Name = existingUser.Name;
        this.DateOfBirth = existingUser.DateOfBirth;
    }

    public override void CommitChanges()
    {
        this.existingUser.Name = this.Name;
        this.existingUser.DateOfBirth = this.DateOfBirth;
        // possibly make database call here
    }

    public override void Delete()
    {
        // code to delete this.existingUser from database
    }
}

I've found this works really well. It separates my editing logic from my entities, and separates the logic of creating a new entity from editing an existing one. It also creates a place to put logic that's common to both new and existing entities (such as the Age calculated property, and yes I know it's not implemented right :)

Not the answer you're looking for? Browse other questions tagged or ask your own question.