views:

1096

answers:

21

This is quite a controversial topic, and before you say "no", is it really, really needed?

I have been programming for about 10 years, and I can't honestly say that I can recall a time where inheritance solved a problem that couldn't be solved another way. On the other hand I can recall many times when I used inheritance, because I felt like I had to or because I though I was clever and ended up paying for it.

I can't really see any circumstances where, from an implementation stand point, aggregation or another technique could not be used instead of inheritance.

My only caveat to this is that we would still allow inheritance of interfaces.

(Update)

Let's give an example of why it's needed instead of saying, "sometimes it's just needed." That really isn't helpful at all. Where is your proof?

(Update 2 Code Example)

Here's the classic shape example, more powerful, and more explicit IMO, without inheritance. It is almost never the case in the real world that something really "Is a" of something else. Almost always "Is Implemented in Terms of" is more accurate.

public interface IShape
{
    void Draw();
}

public class BasicShape : IShape
{
    public void Draw()
    {
        // All shapes in this system have a dot in the middle except squares.
        DrawDotInMiddle();
    }
}

public class Circle : IShape
{
    private BasicShape _basicShape;

    public void Draw()
    {
        // Draw the circle part
        DrawCircle();
        _basicShape.Draw();
    }
}

public class Square : IShape
{
    private BasicShape _basicShape;

    public void Draw()
    {
        // Draw the circle part
        DrawSquare();
    }
}
A: 

I suppose the only instance where inheritance of types is required is where you want to provide a default implementation. An interface is really just a pure virtual abstract class.

Mitch Wheat
Even in this case. Can you just provide an implementation for an interface, and make the classes that you want to have "inherit" from that default implementation just contain an instance of that class and delegate all calls to it?
John Sonmez
Yes, but that violates the actual principles of OO design. Those principles exist so that anyone looking at the design can understand it. Altering the rules of the game actually makes the design harder to understand, undermining the point of the design effort.
Harper Shelby
+1  A: 

No. Sometimes you need inheritance. And for those times where you don't -- don't use it. You can always "just" use interfaces (in languages that have them) and ADPs without data work like interfaces in those languages that don't have them. But I see no reason to remove what is sometimes a necessary feature just because you feel it isn't always needed.

jmucchiello
Show me one instance where it is absolutely needed.
John Sonmez
Obviously it's never "absolutely" needed - a Turing complete programming language exists which does not have inheritance. Or classes. Or objects. Or built-in loops. Whether something is needed or not is subjective, and if you really hate a feature then you'll find a way around it.
Steve Jessop
+1  A: 

No. Just because it's not often needed, doesn't mean it's never needed. Like any other tool in a toolkit, it can (and has been, and will be) misused. However, that doesn't mean it should never be used. In fact, in some languages (C++), there is no such thing as an 'interface' at the language level, so without a major change, you couldn't prohibit it.

Harper Shelby
+1  A: 

a lot of the time I find myself choosing a base class over an interface just because I have some standard functionality. in C#, I can now use extension methods to achieve that, but it still doesn't achieve the same thing for several situations.

Jimmy
+15  A: 

I blogged about this as a wacky idea a while ago.

I don't think it should be removed, but I think classes should be sealed by default to discourage inheritance when it's not appropriate. It's a powerful tool to have available, but it's like a chain-saw - you really don't want to use it unless it's the perfect tool for the job. Otherwise you might start losing limbs.

The are potential language features such as mix-ins which would make it easier to live without, IMO.

Jon Skeet
OMG Jon, I can't believe I actually have to disagree with one of your answers! Inheritance is fundamental to object-oriented programming, without it you only have object-based programming, which is not nearly as powerful. Telling all future developers they cannot derive from your class is sinful...
Steven A. Lowe
@Steven: Whereas I believe that letting people derive from your class without you preparing for it (which takes a lot of work) is much more dangerous. Josh Bloch explains it better than I can - see the appropriate item in Effective Java, 2nd edition.
Jon Skeet
@Jon: The problem isn't that inheritance exists, the problem is that it exists without *multiple* inheritance which removes the need for "rooted hierarchies" and therefore you almost never runs into these problems you're illustrating... Though I agree with your "sealed by default" approach...
Thomas Hansen
+9  A: 

Inheritance can be rather useful in situations where your base class has a number of methods with the same implementation for each derived class, to save every single derived class from having to implement boiler-plate code. Take the .NET Stream class for example which defines the following methods:

public virtual int Read(byte[] buffer, int index, int count)
{
}

public int ReadByte()
{
    // note: this is only an approximation to the real implementation
    var buffer = new byte[1];
    if (this.Read(buffer, 0, 1) == 1)
    {
        return buffer[0];
    }

    return -1;
}

Because inheritance is available the base class can implement the ReadByte method for all implementations without them having to worry about it. There are a number of other methods like this on the class which have default or fixed implementations. So in this type of situation it's a very valuable thing to have, compared with an interface where your options are either to make everyone re-implement everything, or to create a StreamUtil type class which they can call (yuk!).

To clarify, with inheritance all I need to write to create a DerivedStream class is something like:

public class DerivedStream : Stream
{
    public override int Read(byte[] buffer, int index, int count)
    {
        // my read implementation
    }
}

Whereas if we're using interfaces and a default implementation of the methods in StreamUtil I have to write a bunch more code:

public class DerivedStream : IStream
{
    public int Read(byte[] buffer, int index, int count)
    {
        // my read implementation
    }

    public int ReadByte()
    {
        return StreamUtil.ReadByte(this);
    }
}

}

So it's not a huge amount more code, but multiply this by a few more methods on the class and it's just unnecessary boiler plate stuff which the compiler could handle instead. Why make things more painful to implement than necessary? I don't think inheritance is the be-all and end-all, but it can be very useful when used correctly.

Greg Beech
What about a class that would inherit from Stream instead inheriting from IStream, and containing an instance of DefaultStream. For its ReadByte method it calls DefaultStream.ReadByte().
John Sonmez
That's effectively what I said with the StreamUtil class. Sure, it could be done, but why would you want to split the implementation in two? And even then the derived class still has to write the method prototypes and pass-throughs. Inheritance is just cleaner in this case.
Greg Beech
The extra code to wrap the methods for delegation, is more clear in my opinion than classes having methods that are not defined in the class. A little extra boilerplate code, but a much more specific intention. It is very clear what is happening when you delegate, but inheritance is not always.
John Sonmez
You could say the same thing about iterators (yield return) - writing a state machine manually makes it clearer how the iteration works, as you can't even see the generated code unless you disassemble the assembly, but do you really want to write all that boiler plate code?
Greg Beech
This example is exactly what mixins are for. One of the things mixins do is "interface expansion", where you implement a small interface, and the mixin fills it out to a larger, more user-friendly interface. I'd agree languages need mixins, but that doesn't necessarily mean they need inheritance.
Steve Jessop
By "need" there, I actually mean "should have, if avoiding this kind of boilerplate is a concern". Which I agree that it usually is.
Steve Jessop
I would suggest creating a StreamUtil class, but rather a StreamDefault, or StreamBasic. In your "derived" class you would create a new object of the StreamBasic class, and delegate the calls to it as needed.
John Sonmez
Sure, mixins can also be used to solve the problem, assuming they allow their default implementations of methods to be overridden (e.g. Flush should be defaulted to no-op but must be overridable). But this doesn't solve the complaint above that you're silently gaining implementation from elsewhere.
Greg Beech
+1  A: 

My initial thought was, You're crazy. But after thinking about it a while I kinda agree with you. I'm not saying remove Class Inheritance fully (abstract classes with partial implementation for example can be useful), but I have often inherited (pun intended) badly written OO code with multi level class inheritance that added nothing, other than bloat, to the code.

KiwiBastard
+2  A: 

For production code I almost never use inheritance. I go with using interfaces for everything (this helps with testing and improves readability i.e. you can just look at the interface to read the public methods and see what is going on because of well-named methods and class names). Pretty much the only time I would use inheritance would be because a third party library demands it. Using interfaces, I would get the same effect but I would mimic inheritance by using 'delegation'.

For me, not only is this more readable but it is much more testable and also makes refactoring a whole lot easier.

The only time I can think of that I would use inheritance in testing would be to create my own specific TestCases used to differentiate between types of tests I have in my system.

So I probably wouldn't get rid of it but I choose not to use it as much as possible for the reasons mentioned above.

digiarnie
+1  A: 

Note that inheritance means it is no longer possible to supply the base class functionality by dependency injection, in order to unit test a derived class in isolation of its parent.

So if you're deadly serious about dependency injection (which I'm not, but I do wonder whether I should be), you can't get much use out of inheritance anyway.

Steve Jessop
+4  A: 

Inheritance is one of those tools that can be used, and of course can be abused, but I think languages have to have more changes before class-based inheritance could be removed.

Let's take my world at the moment, which is mainly C# development.

For Microsoft to take away class-based inheritance, they would have to build in much stronger support for handling interfaces. Things like aggregation, where I need to add lots of boiler-plate code just to wire up an interface to an internal object. This really should be done anyway, but would be a requirement in such a case.

In other words, the following code:

public interface IPerson { ... }
public interface IEmployee : IPerson { ... }
public class Employee : IEmployee
{
    private Person _Person;
    ...

    public String FirstName
    {
        get { return _Person.FirstName; }
        set { _Person.FirstName = value; }
    }
}

This would basically have to be a lot shorter, otherwise I'd have lots of these properties just to make my class mimic a person good enough, something like this:

public class Employee : IEmployee
{
    private Person _Person implements IPerson;
    ...
}

this could auto-create the code necessary, instead of me having to write it. Just returning the internal reference if I cast my object to an IPerson would do no good.

So things would have to be better supported before class-based inheritance could be taken off the table.

Also, you would remove things like visibility. An interface really just have two visibility settings: There, and not-there. In some cases you would be, or so I think, forced to expose more of your internal data just so that someone else can more easily use your class.

For class-based inheritance, you can usually expose some access points that a descendant can use, but outside code can't, and you would generally have to just remove those access points, or make them open to everyone. Not sure I like either alternative.

My biggest question would be what specifically the point of removing such functionality would be, even if the plan would be to, as an example, build D#, a new language, like C#, but without the class-based inheritance. In other words, even if you plan on building a whole new language, I still am not entirely sure what the ultimate goal would be.

Is the goal to remove something that can be abused if not in the right hands? If so, I have a list a mile long for various programming languages that I would really like to see addresses first.

At the top of that list: The with keyword in Delphi. That keyword is not just like shooting yourself in the foot, it's like the compiler buys the shotgun, comes to your house and takes aim for you.

Personally I like class-based inheritance. Sure, you can write yourself into a corner. But we can all do that. Remove class-based inheritance, I'll just find a new way of shooting myself in the foot with.

Now where did I put that shotgun...

Lasse V. Karlsen
+1  A: 

No, it is not needed, but that does not mean it does not provide an overall benefit, which I think is more important than worrying about whether it is absolutely necessary.

In the end, almost all modern software language constructs amount to syntactic sugar - we could all be writing assembly code (or using punch cards, or working with vacuum tubes) if we really had to.

I find inheritance immensely useful those times that I truly want to express an "is-a" relationship. Inheritance seems to be the clearest means of expressing that intent. If I used delegation for all implementation re-use, I lose that expressiveness.

Does this allow for abuse? Of course it does. I often see questions asking how the developer can inherit from a class but hide a method because that method should not exist on the subclass. That person obviously misses the point of inheritance, and should be pointed toward delegation instead.

I don't use inheritance because it is needed, I use it because it is sometimes the best tool for the job.

JeremyDWill
+4  A: 

Of course you can write great programs happily without objects and inheritance; functional programmers do it all the time. But let us not be hasty. Anybody interested in this topic should check out the slides from Xavier Leroy's invited lecture about classes vs modules in Objective Caml. Xavier does a beautiful job laying out what inheritance does well and does not do well in the context of different kinds of software evolution.

All languages are Turing-complete, so of course inheritance isn't necessary. But as an argument for the value of inheritance, I present the Smalltalk blue book, especially the Collection hierarchy and the Number hierarchy. I'm very impressed that a skilled specialist can add an entirely new kind of number (or collection) without perturbing the existing system.

I will also remind questioner of the "killer app" for inheritance: the GUI toolkit. A well-designed toolkit (if you can find one) makes it very, very easy to add new kinds of graphical interaction widgets.

Having said all that, I think that inheritance has innate weaknesses (your program logic is smeared out over a large set of classes) and that it should be used rarely and only by skilled professionals. A person graduating with a bachelor's degree in computer science barely knows anything about inheritance---such persons should be permitted to inherit from other classes at need, but should never, ever write code from which other programmers inherit. That job should be reserved for master programmers who really know what they're doing. And they should do it reluctantly!

For an interesting take on solving similar problems using a completely different mechanism, people might want to check out Haskell type classes.

Norman Ramsey
You can't do real oop without inheritance imo.
Spikolynn
Read about Self (http://research.sun.com/self/papers/self-power.html) and see if you still think so.
Norman Ramsey
+2  A: 

I guess I have to play the devil's advocate. If we didn't have inheritance then we wouldn't be able to inherit abstract classes that uses the template method pattern. There are lots of examples where this is used in frameworks such as .NET and Java. Thread in Java is such an example:

// Alternative 1:
public class MyThread extends Thread {

    // Abstract method to implement from Thread
    // aka. "template method" (GoF design pattern)
    public void run() {
        // ...
    }
}

// Usage:
MyThread t = new MyThread();
t.start();

The alternative is, in my meaning, verbose when you have to use it. Visual clutteer complexity goes up. This is because you need to create the Thread before you can actually use it.

// Alternative 2:
public class MyThread implements Runnable {
    // Method to implement from Runnable:
    public void run() {
        // ...
    }
}

// Usage:
MyThread m = new MyThread();
Thread t = new Thread(m);
t.start();
// …or if you have a curious perversion towards one-liners
Thread t = new Thread(new MyThread());
t.start();

Having my devil's advocate hat off I guess you could argue that the gain in the second implementation is dependency injection or seperation of concerns which helps designing testable classes. Depending on your definition of what an interface is (I've heard of at least three) an abstract class could be regarded as an interface.

Spoike
A: 

Here's a nice view at the topic:

IS-STRICTLY-EQUIVALENT-TO-A by Reg Braithwaite

krusty.ar
+1  A: 

Is inheritance really needed? Depends what you mean by "really". You could go back to punch cards or flicking toggle switches in theory, but it's a terrible way to develop software.

In procedural languages, yes, class inheritance is a definite boon. It gives you a way to elegantly organise your code in certain circumstances. It should not be overused, as any other feature should not be overused.

For example, take the case of digiarnie in this thread. He/she uses interfaces for nearly everything, which is just as bad as (possibly worse than) using lots of inheritance.

Some of his points :

this helps with testing and improves readability

It doesn't do either thing. You never actually test an interface, you always test an object, that is, an instantiation of a class. And having to look at a completely different bit of code helps you understand the structure of a class? I don't think so.

Ditto for deep inheritance hierarchies though. You ideally want to look in one place only.

Using interfaces, I would get the same effect but I would mimic inheritance by using 'delegation'.

Delegation is a very good idea, and should often be used instead of inheritance (for example, the Strategy pattern is all about doing exactly this). But interfaces have zero to do with delegation, because you cannot specify any behaviour at all in an interface.

also makes refactoring a whole lot easier.

Early commitment to interfaces usually makes refactoring harder, not easier, because there are then more places to change. Overusing inheritance early is better (well, less bad) than overusing interfaces, as pulling out delegate classes is easier if the classes being modified do not implement any interfaces. And it's quite often from those delegates than you get useful interfaces.

So overuse of inheritance is a bad thing. Overuse of interfaces is a bad thing. And ideally, a class will neither inherit from anything (except maybe "object" or the language equivalent), nor implement any interfaces. But that doesn't mean either feature should be removed from a language.

Jim Cooper
+3  A: 

I wish languages would provide some mechanisms to make it easier to delegate to member variables. For example, suppose interface I has 10 methods, and class C1 implements this interface. Suppose I want to implement class C2 that is just like a C1 but with method m1() overridden. Without using inheritance, I would do this as follows (in Java):

public class C2 implements I {
    private I c1;

    public C2() {
       c1 = new C1();
    }

    public void m1() {
        // This is the method C2 is overriding.
    }

    public void m2() {
        c1.m2();
    }

    public void m3() {
        c1.m3();
    }

    ...

    public void m10() {
        c1.m10();
    }
}

In other words, I have to explicitly write code to delegate the behavior of methods m2..m10 to the member variable m1. That's a bit of a pain. It also clutters the code up so that it's harder to see the real logic in class C2. It also means that whenever new methods are added to interface I, I have to explicitly add more code to C1 just to delegate these new methods to C1.

I wish languages would allow me to say: C1 implements I, but if C1 is missing some method from I, automatically delegate to member variable c1. That would cut down the size of C1 to just

public class C2 implements I(delegate to c1) {
    private I c1;

    public C2() {
       c1 = new C1();
    }

    public void m1() {
        // This is the method C2 is overriding.
    }
}

If languages allowed us to do this, it would be much easier to avoid use of inheritance.

Here's a blog article I wrote about automatic delegation.

Clint Miller
A: 

If there is a framework class that does almost exactly what you want, but a particular function of its interface throws a NotSupported exception or for some other reason you only want to override one method to do something specific to your implementation, it's much easier to write a subclass and override that one method rather than write a brand new class and write pass-throughs for each of the other 27 methods in the class.

Similarly, What about Java, for example, where every object inherits from Object, and therefore automatically has implementations of equals, hashcode, etc. I don't have to re-implement them, and it "just works" when I want to use the object as a key in a hashtable. I don't have to write a default passthrough to a Hashtable.hashcode(Object o) method, which frankly seems like it's moving away from object orientation.

Ed Marty
+3  A: 

Needed? No. You can write any program in C, for example, which doesn't have any sort of inheritance or objects. You could write it in assembly language, although it would be less portable. You could write it in a Turing machine and have it emulated. Somebody designed a computer language with exactly one instruction (something like subtract and branch if not zero), and you could write your program in that.

So, if you're going to ask if a given language feature is necessary (like inheritance, or objects, or recursion, or functions), the answer is no. (There are exceptions - you have to be able to loop and do things conditionally, although these need not be supported as explicit concepts in the language.)

Therefore, I find questions of this sort useless.

Questions like "When should we use inheritance" or "When shouldn't we" are a lot more useful.

David Thornley
+4  A: 

Have fun implementing ISystemObject on all of your classes so that you have access to ToString() and GetHashcode().

Additionally, good luck with the ISystemWebUIPage interface.

If you don't like inheritance, my suggestion is to stop using .NET all together. There are way too many scenarios where it saves time (see DRY: don't repeat yourself).

If using inheritance is blowing up your code, then you need to take a step back and rethink your design.

I prefer interfaces, but they aren't a silver bullet.

A: 

The question is, "Should inheritance (of non-interface types) be removed from programming languages?"

I say, "No", as it will break a hell of a lot of existing code.

That aside, should you use inheritance, other than inheritance of interfaces? I'm predominantly a C++ programmer and I follow a strict object model of multiple inheritance of interfaces followed by a chain of single inheritance of classes. The concrete classes are a "secret" of a component and it's friends, so what goes on there is nobodies business.

To help implement interfaces, I use template mixins. This allows the interface designer to provide snippets of code to help implement the interface for common scenarios. As a component developer I feel like I can go mixin shopping to get the reusable bits without being encumbered by how the interface designer thought I should build my class.

Having said that, the mixin paradigm is pretty much unique to C++. Without this, I expect that inheritance is very attractive to the pragmatic programmer.

Daniel Paull
+1  A: 

I believe a better mechanism for code re-use which is sometimes achieved through inheritance are traits. Check this link (pdf) for a great discussion on this, including the distinction between traits and mixins, and why traits are favored.

There's some research that introduces traits into C# (pdf).

Perl has traits through Moose::Roles. Scala traits are like mixins, as in Ruby.

Jordão