67

I know the question has been discussed before, but it seems always under the assumption that inheritance is at least sometimes preferable to composition. I'd like to challenge that assumption in hopes of gaining some understanding.

My question is this: Since you can accomplish anything with object composition that you can with classical inheritance and since classical inheritance is very often abused[1] and since object composition gives you flexibility to change the delegate object runtime, why the would you ever use classical inheritance?

I can sort of understand why you would recommend inheritance in some languages like Java and C++ that do not offer convenient syntax for delegation. In these languages you can save a lot of typing by using inheritance whenever it is not clearly incorrect to do so. But other languages like Objective C and Ruby offer both classical inheritance and very convienient syntax for delegation. The Go programming language is the only langage that to my knowledge has decided that classical inheritance is more trouble than it's worth and supports only delegation for code reuse.

Another way to state my question is this: Even if you know that classical inheritance is not incorrect to implement a certain model, is that reason enough to use it instead of composition?

[1] Many people use classical inheritance to achieve polymorphism instead of letting their classes implement an interface. The purpose of inheritance is code reuse, not polymorphism. Furthermore, some people use inheritance to model their intuitive understanding of an "is-a" relationship which can often be problematic.

Update

I just want to clarify what I mean exactly when I talk about inheritance:

I am talking about the kind of inheritance whereby a class inherits from a partially or fully implemented base class. I am not talking about inheriting from a purely abstract base class which amounts to the same thing as implementing an interface, which I for the record am not arguing against.

Update 2

I understand that inheritance is the only way to achieve polymorphism i C++. In that case it's obvious why you must use it. So my question is limited to languages such as Java or Ruby that offer distinct ways to achieve polymorphism (interfaces and duck typing, respectively).

Community
  • 1
  • 1
KaptajnKold
  • 10,638
  • 10
  • 41
  • 56
  • 3
    "why the would you ever use classical inheritance?" First you should probably ask opposite question. Why WOULDN'T you use classical inheritance? If a language offers a concept (inheritance in this case), avoiding it because of "religious beliefs" simply adds unnecessary obstacles. There are always multiple ways to do something. You could also ask many other similar questions - "if you can program in asm, why would you ever need C, and if you can program in C++ why would you ever use python". It is just another tool - you ever use it or don't use it. – SigTerm Jul 28 '10 at 11:04
  • 11
    @SigTerm Many languages, even modern ones, support goto. A good reason *not* to use a language feature is when it introduces unnecessary complexity. I am merely trying to understand what – if any – benefits inheritance might have that would make the added complexity worth it. – KaptajnKold Jul 28 '10 at 11:10
  • @KaptajnKold: "goto" I saw situations when goto was useful. In modern langauges. "would make the added complexity worth it" IMO added complexity appears when you'll try to do everything while avoiding inheritance. Let's say you have a list of "resources" somewhere that needs to be treated in special way, and want to add new kind of resource. With (multiple) inheritance it can done in few lines of code - you add to object properties/behavior of resource. Using composition... let's say it will be more complicated. – SigTerm Jul 28 '10 at 11:21
  • 2
    @SigTerm Maybe in Java it would be more complex but it certainly wouldn't in Objective C, Ruby, Go, JavaScript, SmallTalk or any other languages which have better facilities for expressing composition. I've already mentioned that I can see the point of using inheritance if it makes for less verbose code, but is that really the *only* benefit? If so, does it mean that it has *no* benefits in languages with good syntactic support for composition? – KaptajnKold Jul 28 '10 at 11:52
  • 1
    Interfaces are a kludge in the languages they exist in to avoid having to deal with the perceived problems of multiple inheritance. – Powerlord Jul 28 '10 at 13:45
  • Be sure to read the [Is there anything composition cannot accomplish that inheritance can?](http://stackoverflow.com/questions/2238642/is-there-anything-composition-cannot-accomplish-that-inheritance-can) This question is in spirit very nearly a duplicate of that. – Jeff Sternal Jul 28 '10 at 14:31
  • This is at least partly subjective, and the OP is arguing with people in the comments. That, to me, makes it subjective and argumentative. Voting to close. (If this were just an exposition of people's views on the subject I wouldn't vote to close, but the long arguments in the comments are unsuited to SO.) – David Thornley Jul 28 '10 at 14:38
  • I had exactly the same idea, see http://devnet.jetbrains.com/message/5478759 – OlliP Feb 12 '13 at 12:19
  • You can experiment with Groovy's @Delegate annotation which is more powerful than Go's delegate construct. Send me a mail to jeti789 -at- web -dot- de if you like to for further discussion. – OlliP Feb 12 '13 at 12:27
  • Very close duplicate: [is-inheritance-really-needed?](http://stackoverflow.com/questions/278476/is-inheritance-really-needed?lq=1) and [is-there-anything-composition-cannot-accomplish-that-inheritance-can](http://stackoverflow.com/questions/2238642/is-there-anything-composition-cannot-accomplish-that-inheritance-can) – nawfal Oct 03 '13 at 06:41
  • 23
    It is a shame that questions like this are closed and labeled "not constructive". It seems that the admins complain about asking simple questions that someone can just look up, but then block this question, which is very thoughtful and attempts to address a very fundamental problem. There is an answer that exists, although it may be hard to reach it and there may not be a consensus. – TigerBear Jun 17 '14 at 21:49
  • Inheritance is a weird edge case of composition where the inner object will never change, and the outer object should expose and delegate to all of the methods on the inner object. Ultimately, it saves you some keystrokes in this one highly specific scenario, but in almost every case it just creates headaches. As a rule, avoid it like the plague. – weberc2 Dec 12 '15 at 00:00
  • 1
    Inheritance is _not_ the only way to use polymorphism in c++. You also have access to static polymorphism in c++ through templates. I would argue this to be the preferred method, and it works more like interfaces except that they are compile time instead of run time and do not require a formal declaration. They 'just work' when a type is provided that matches the use case, otherwise you get a compile time error. Concepts are being introduced to help make interfacing more formalized and less reliant on implementation details. – David Peterson Apr 05 '18 at 16:40

13 Answers13

54

[note: This question was originally tagged as being language-agnostic. Based on that, this answer was written to be fairly language agnostic, so it discusses inheritance as it's used across a wide range of languages, such as Smalltalk, C++, and Object Pascal. It's since been re-tagged as being specifically about Java. Java is different in defining a class and an interface as two entirely separate things. The idea that the purpose of inheritance is code reuse, not polymorphism is reasonable from a Java-specific viewpoint, but clearly wrong from a language-agnostic viewpoint. If you only care about Java, this probably isn't the best answer.]

The purpose of inheritance is code reuse, not polymorphism.

This is your fundamental mistake. Almost exactly the opposite is true. The primary purpose of (public) inheritance is modeling the relationships between the classes in question. Polymorphism is a large part of that.

When used correctly, inheritance isn't about reusing existing code. Rather, it's about being used by existing code. That is to say, if you have existing code that can work with the existing base class, when you derive a new class from that existing base class that other code can now automatically work with your new derived class as well.

It is possible to use inheritance for code re-use, but when/if you do so it should normally be private inheritance not public inheritance. If the language you're using supports delegation well, chances are pretty good that you rarely have much reason to use private inheritance. OTOH, private inheritance does support a few things that delegation (normally) doesn't. In particular, even though polymorphism is a decidedly secondary concern in this case, it can still be a concern -- i.e., with private inheritance you can start from a base class that's almost what you want, and (assuming it allows it) override the parts that aren't quite right.

With delegation your only real choice is to use the existing class exactly as it stands. If it doesn't do quite what you want, your only real choice is to ignore that functionality completely, and re-implement it from the ground up. In some cases that's no loss, but in others it's quite substantial. If other parts of the base class use the polymorphic function, private inheritance lets you override only the polymorphic function, and the other parts will use your overridden function. With delegation, you can't easily plug in your new functionality so other parts of the existing base class will use what you've overridden.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • I think that in duck typed languages there is no need to inherit from a class to be able to replace it in existing code. A class that delegates everything to another class would most likely be able to replace it. – Alexey Oct 27 '12 at 20:13
  • 4
    After some more thinking, i also think that the purpose of inheritance is code reuse and not polymorphism. For polymorphism it is enough to implement a required interface, but with inheritance you inherit the implementation. – Alexey Oct 29 '12 at 21:36
  • @Alexey: Yes, if you're talking specifically about the languages specified in the OP's "Update 2" (written ~6 months after this answer) that becomes a defensible position (i.e., I'm not sure I agree that it's entirely correct, but at least it's not nearly as obviously nonsense). – Jerry Coffin Oct 29 '12 at 22:09
  • @ Jerry: i agree that inheritance can be also useful for polymorphism even in languages like Ruby: in my opinion in such cases it serves as a class contract description. – Alexey Nov 03 '12 at 10:01
  • 1
    Really, you shouldn't use inheritance in most circumstances. If you want code reuse, define an interface that the would-be parent class implements, make the parent class a member of the "child" class, and expose the same methods in the child as exist in the parent. It's tedious, but it's a better system than with inheritance polymorphism, and it's not tedious in sane languages that give you this for free, a la golang. :) – weberc2 Nov 15 '13 at 20:59
  • 2
    @weberc2: If you're using Go, that's about your only alternative. In something that actually has inheritance, all you're doing is imitating what inheritance already does, but making it harder to read, harder to use, and generally just worse. Yes, many people over-use inheritance (especially in Java, from what I've seen), but if you want all (or at least 90%) of what inheritance provides, simulating all of it by hand instead is *not* an improvement. Oh, but the downvote got my rep back to a multiple of 5, so thanks even though it's completely unwarranted. – Jerry Coffin Nov 15 '13 at 21:28
  • 1
    @JerryCoffin How do you figure that it's the only alternative in Go? You aren't imitating what inheritance already does, you're decoupling your "child" class from the "parent" class _implementation_. <- That's the improvement. It's only "doing it by hand" because most languages don't offer tools to Do It Right by default. ;) Anyway, I didn't downvote you because you disagree with my philosophy, but because you're objectively wrong. I'm glad all is well with your reputation. Cheers. – weberc2 Nov 15 '13 at 22:22
  • 1
    @weberc2: If there's really a factual error in the answer, I'll be happy to correct it, but at least so far you don't seem to have pointed to anything close to a factual error. – Jerry Coffin Nov 15 '13 at 22:37
  • 1
    @JerryCoffin I don't particularly care if you update your answer or not, but I don't understand why you disagree. Do you think loose coupling is bad? Or do you think that implementation inheritance offers a looser coupling than interface inheritance? – weberc2 Nov 18 '13 at 15:24
  • 2
    @weberc2: Disagree with *what* exactly? So far about the closest thing to a factual statement you've made is implying that you like Go. I certainly don't disagree with that. You claimed that the answer was objectively wrong. If so, cite a sentence (or two, or whatever), and specify how it's wrong. Asking vague questions about do I think X or Y isn't showing anything about the answer being objectively wrong. – Jerry Coffin Nov 18 '13 at 15:32
  • 1
    @JerryCoffin You stated, "In something that actually has inheritance, all you're doing is imitating what inheritance already does". I believe this is objectively wrong. Consider this example of interface inheritance: http://pastebin.com/xAybHaDJ How would you do this with classical inheritance? Would you derive a new class for every combination of Reader and Writer? – weberc2 Nov 18 '13 at 17:55
  • @weberc2: So the (first) problem here is that you don't understand the difference between an answer and a comment. These are comments. The answer is the part in larger type above. – Jerry Coffin Nov 18 '13 at 18:03
19

The main reason for using inheritance is not as a form of composition - it is so you can get polymorphic behaviour. If you don't need polymorphism, you probably should not be using inheritance, at least in C++.

  • 4
    I respectfully disagree: Inheritance is *not* about polymorphism. That's what interfaces are for. I agree that polymorphism is what inheritance is most often used for, and that's part of my point: Inheritance is abused for things it is not best suited for. – KaptajnKold Jul 28 '10 at 10:29
  • 5
    @Kap Well, what can I say, except "you are wrong" - C++ (for example) does not have the concept of interfaces. And the only time I use inheritance in my own code is when I need polymorphism. –  Jul 28 '10 at 10:31
  • 1
    I did not know that C++ had no concept of interfaces. My mistake. In that case you are obviously required to use inheritance to achieve polymorphism. But let's say you decided to only inherit from purely abstract classes. Would you feel limited by that, or are there in your opinion good reasons to use inheritance from non-abstract classes? – KaptajnKold Jul 28 '10 at 10:45
  • 2
    @Kap In C++, it is considered best practice to only inherit from abstract classes. Most of us duck this at one point or another (and regret it later), but base classes are almost always abstract - I don't see this as a limitation on me. –  Jul 28 '10 at 10:49
  • 2
    Well, then you've practically proved my point :-) – KaptajnKold Jul 28 '10 at 10:54
  • 2
    @Kap I thought your point was that you can replace inheritance with composition? –  Jul 28 '10 at 10:56
  • 2
    Yes, it is. But you need to differentiate between inheritance of an implementation and inheritance of an interface (or purely abstract class). I am only talking about the former kind. – KaptajnKold Jul 28 '10 at 11:12
  • 1
    @Kap So your question is really "Is there any case where it is preferable to use inheritance to replace composition?" - somewhat different to "Why use inheritance at all?", I think you will agree. –  Jul 28 '10 at 11:16
  • "But you need to differentiate between inheritance of an implementation and inheritance of an interface (or purely abstract class)" I don't see a big difference here. Why don't you look at Qt 4 or any other GUI library for C++? They should be enough to illustrate when inheritance is useful. – SigTerm Jul 28 '10 at 11:23
  • 2
    @Neil No, i don't agree. IMO it is you who are confusing two distinct concepts because they share the same syntax in C++. There is less reason for confusion among Java programmers, because the two concepts are distinct in syntax also. I'll admit to having a bit of a problem myself because I do not know of a substantive to describe the kind of inheritance we both like but which in my opinion is not really inheritance at all. Feel free to enlighten me if you know of one. – KaptajnKold Jul 28 '10 at 11:41
  • 1
    @SigTerm I don't doubt there are applications and frameworks that use classical inheritance while avoiding all of the problems it can get you. But my question remains: What are they gaining by this that they couldn't also have gained if they had used composition? When is classical inheritance better than composition and why? – KaptajnKold Jul 28 '10 at 11:44
  • 2
    Neil said "In C++, it is considered best practice to only inherit from abstract classes." He talked about abstract classes, but not necessarily *purely* abstract classes (which correspond to Java-style interfaces). I think inheriting from an abstract class that is not purely abstract is entirely fine. – Philipp Jul 28 '10 at 11:46
  • 2
    @Philipp You may be right, but I'm still nowhere nearer to understanding what the *concrete* benefits are :-( – KaptajnKold Jul 28 '10 at 11:57
  • 2
    @Kap Well, you seem to have your own, unique definition of inheritance. And I'm still not clear what question you are asking and, from your comments, neither are you. But one last try - good C++ programmers do not use inheritance (classical or otherwise) as a substitute for composition. –  Jul 28 '10 at 11:59
  • 1
    @Neil You're not trying hard enough ;-). Re. my "unique definition": I am not alone in making a distinction between implementing an interface and inheriting an implementation. Gang Of Four makes this same distinction. But let me try to rephrase the question for you: Do you think inheriting from an non-abstract class in C++ is a useful feature? If so, when would you recommend doing so instead of using a delegate object to achieve the same result? – KaptajnKold Jul 28 '10 at 12:29
  • 2
    @Kap As I've said (at least twice) the purpose of inheritance in C++ is to provide polymorphism; to do this it is best to derive from abstract classes. I would not recommend its use in other cases. And the C++ in the GoF book is pretty poor stuff. –  Jul 28 '10 at 12:31
  • 2
    @Neil I'm sorry if you feel you have to repeat yourself, but it was you who claimed to still not understand my question, which is why I restated it. I don't feel as if I've had any trouble understanding your points and in fact feel like we've never been very far from each other: You explicitly do not recommend using inheritance from anything other than an abstract class. It is the fact that many languages also support *that other kind of inheritance*, you know, the kind you do not recommend, that made me pose the original question. – KaptajnKold Jul 28 '10 at 13:16
  • 1
    @Kap I explicitly do not recommend using inheritance to do anything but implement polymorphism - it's certainly possible to do this with non-abstract classes.As for us not being far from each other, when you come out with statements like "Inheritance is not about polymorphism" (in your first comment), then yes, we are. But of course then you were talking about this mysterious "other" kind of inheritance, I suppose. –  Jul 28 '10 at 13:57
  • 2
    @Kap, if you specify 'implementation inheritance' you may be able to keep this from spiraling out of control. – Jeff Sternal Jul 28 '10 at 14:29
  • @Neil Re. "Inheritance is not about polymorphism": I ceded this point to you in my 2nd comment, but you must have missed it. But if you do not agree that there are 2 distinct uses for inheritance in C++ I guess there's not more I can say at this point to convince you. You've completely ignored that many other languages have a separate mechanism to achieve polymorphism, whether it be interfaces in Java or duck typing in Ruby. You ignore that inheritance in these languages is done to achieve something more than polymorphism, or there would be no reason to have this feature also. – KaptajnKold Jul 28 '10 at 14:43
  • @Jeff The last paragraph in my original question was meant to clarify this distinction. – KaptajnKold Jul 28 '10 at 14:46
  • @Neil Wikipedia explains the distinction better than I could hope to: http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming) – KaptajnKold Jul 28 '10 at 15:45
  • Sorry. SO eats the closing paranthesis for some reason. Just add it, or look up "inheritance (object oriented programming)" manually. – KaptajnKold Jul 28 '10 at 17:07
  • @KaptajnKold: I think you are trying to describe interface inheritance aka subtype polymorphism. –  Jul 28 '10 at 17:25
  • 1
    http://en.wikipedia.org/wiki/Inheritance_%28object-oriented_programming%29 - and about as useful as most wikipedia articles. –  Jul 28 '10 at 17:27
  • 4
    @KaptajnKold: "What are they gaining by this that they couldn't also have gained if they had used composition?" Honestly, I don't see a point of this discussion. IMO your questions are too abstract and too far from reality to be useful. Why don't you simply check real APIs? If you want to know what you gain from using inheritance instead of other techniques, simply find inheritance-based API, and redo it (at least part of it) using your favorite technique (the one you think is better than inheritance). In this case you'll get a live demonstration of all benefits and disadvantages. – SigTerm Jul 28 '10 at 18:08
  • 2
    @KaptajnKold: Without real examples, the whole discussion looks like some kind of talk about migrations of non-existent flying pink elephants. Take a Qt or real GUI api. I don't see how you could do it (in C++, at least) without inheritance. If you think it can be done differently, do it differently to illustrate your point. If you think it can be done in Go/Ruby/Whatever, then do it in that language. Compare results (inheritance/no inheritance), think about differences, and you'll get your answers. Purely abstract discussion looks a bit useless for me. – SigTerm Jul 28 '10 at 18:11
19

If you delegate everything that you haven't explicitly overridden to some other object implementing the same interface (the "base" object), then you've basically Greenspunned inheritance on top of composition, but (in most languages) with a lot more verbosity and boilerplate. The purpose of using composition instead of inheritance is so that you can only delegate the behaviors you want to delegate.

If you want the object to use all the behavior of the base class unless explicitly overridden, then inheritance is the simplest, least verbose, most straightforward way to express it.

dsimcha
  • 67,514
  • 53
  • 213
  • 334
  • 6
    Another big advantage of composition is the ability to change the object that you are delegating to at run time. It would be like inheriting from a parent, but then being able to specify a different parent to inherit from at run time. So even if you just delegate out all of your methods, there is still a big advantage. Especially when testing and mocking. – TigerBear Jun 17 '14 at 21:45
  • 3
    Yeah, inheritance is just a weird special case of composition that unreasonably fixes the inner element. There is probably a case in which inheritance might save you some keystrokes, but it doesn't justify all of the confusion and inappropriate uses that it has created. – weberc2 Dec 11 '15 at 23:50
  • 2
    In case the word "Greenspunned" above is unfamiliar, it means bringing a feature from another language into your own, but implementing it badly. See [Greenspun's tenth rule](https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule) and [Leaky Greenspunned Abstractions](https://raganwald.com/2013/08/01/leaky-greenspunned-abstractions.html). – Grandpa Jan 11 '20 at 13:51
7

Every one knows polymorphism is a great advantage of inheritance. Another Benefit which i find in inheritance is that helps to create replica of real world. For example in pay roll system we deal managers developers ,office boys etc. if we inherit all these class with super class Employee. it makes our program more understandable in context of real world that all these classes are basically employees. And one more thing classes not only contain methods they also contain attributes. So if we contain attributes generic to employee in the Employee class like social security number age etc. it would provide greater code reuse and conceptual clarity and of course polymorphism. However while using inheritance things we should keep in mind is the basic design principle "Identify the aspects of your application that vary and separate them from that aspects which change". You should never implement those aspect of application that change by inheritance instead use composition. And for those aspects which are not changeable u should use inheritance ofcourse if an obvious "is a" relation lies.

faisalbhagat
  • 2,142
  • 24
  • 27
  • 1
    Employee should be the interface, and all of the concrete classes should implement the interface. If all concrete classes have the same data, you should probably make Employee a class with a `Type` field for what kind of employee it is. Inheritance is not about polymorphism, that's what interfaces are for. – weberc2 Dec 11 '15 at 23:54
6

Inheritance is to be preferred if:

  1. You need to expose the whole API of the class you extend (with delegation, you will need to write lots of delegating methods) and your language doesn't offer a simple way to say "delegate all unknown methods to".
  2. You need to access protected fields/methods for languages that have no concept of "friends"
  3. The advantages of delegation are somewhat reduced if your language allows multi-inheritance
  4. You usually have no need delegation at all if your language allows to dynamically inherit from a class or even an instance at runtime. You don't need it at all if you can control which methods are exposed (and how they are exposed) at the same time.

My conclusion: Delegation is a workaround for a bug in a programming language.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Re 1) That's why I wrote that inheritance sort of makes sense in some languages, namely the ones that make delegation very verbose. Re 2) Possibly. But you'd have to work hard to convince me that such a need is not a flaw in the design to begin with. Re 3) I don't see why. Re 4) This has more to with overcoming the limitations of inheritance, which demonstrates my point. Inheritance is limiting and difficult to get right. Delegation does not seem to have the same problems. – KaptajnKold Jul 28 '10 at 10:34
  • 1
    Languages like Java make delegation hard, so inheritance is used very often, even if delegation would have been better. – Aaron Digulla Jul 28 '10 at 11:55
  • Do you then agree that inheritance in languages that make delegation easy (e.g. Objective C) is more trouble than it's worth? – KaptajnKold Jul 28 '10 at 12:00
  • I have never used Objective C, so I can't comment on that. – Aaron Digulla Jul 28 '10 at 12:22
4

I always think twice before using inheritance as it can get tricky fast. That being said there are many cases where it simply produces the most elegant code.

ChaosPandion
  • 77,506
  • 18
  • 119
  • 157
3

Interfaces only define what an object can do and not how. So in simple terms interfaces are just contracts. All objects that implement the interface will have to define their own implementation of the contract. In practical world, this gives you separation of concern. Imagine yourself writing an application that needs to deal with various objects you don't know them in advance, still you need to deal with them, only thing you know is what all different things those objects are supposed to do. So you'll define an interface and mention all operations in the contract. Now you'll write your application against that interface. Later whoever wants to leverage your code or application will have to implement the interface on the object to make it work with your system. Your interface will force their object to define how each operation defined in the contract is supposed to be done. This way anyone can write objects that implement your interface, in order to have them flawlessly adapt to your system and all you know is what needs to be done and it is the object that needs to define how it is done.

In real-world development this practice is generally known as Programming to Interface and not to Implementation.

Interfaces are just contracts or signatures and they don't know anything about implementations.

Coding against interface means, the client code always holds an Interface object which is supplied by a factory. Any instance returned by the factory would be of type Interface which any factory candidate class must have implemented. This way the client program is not worried about implementation and the interface signature determines what all operations can be done. This can be used to change the behavior of a program at run-time. It also helps you to write far better programs from the maintenance point of view.

Here's a basic example for you.

public enum Language
{
    English, German, Spanish
}

public class SpeakerFactory
{
    public static ISpeaker CreateSpeaker(Language language)
    {
        switch (language)
        {
            case Language.English:
                return new EnglishSpeaker();
            case Language.German:
                return new GermanSpeaker();
            case Language.Spanish:
                return new SpanishSpeaker();
            default:
                throw new ApplicationException("No speaker can speak such language");
        }
    }
}

[STAThread]
static void Main()
{
    //This is your client code.
    ISpeaker speaker = SpeakerFactory.CreateSpeaker(Language.English);
    speaker.Speak();
    Console.ReadLine();
}

public interface ISpeaker
{
    void Speak();
}

public class EnglishSpeaker : ISpeaker
{
    public EnglishSpeaker() { }

    #region ISpeaker Members

    public void Speak()
    {
        Console.WriteLine("I speak English.");
    }

    #endregion
}

public class GermanSpeaker : ISpeaker
{
    public GermanSpeaker() { }

    #region ISpeaker Members

    public void Speak()
    {
        Console.WriteLine("I speak German.");
    }

    #endregion
}

public class SpanishSpeaker : ISpeaker
{
    public SpanishSpeaker() { }

    #region ISpeaker Members

    public void Speak()
    {
        Console.WriteLine("I speak Spanish.");
    }

    #endregion
}

alt text http://ruchitsurati.net/myfiles/interface.png

this. __curious_geek
  • 42,787
  • 22
  • 113
  • 137
2

What about the template method pattern? Let's say you have a base class with tons of points for customizable policies, but a strategy pattern doesn't make sense for at least one of the following reasons:

  1. The customizable policies need to know about the base class, can only be used with the base class and don't make sense in any other context. Using strategy instead is do-able but a PITA because both the base class and the policy class need to have references to each other.

  2. The policies are coupled to each other in that it wouldn't make sense to freely mix-and-match them. They only make sense in a very limited subset of all possible combinations.

dsimcha
  • 67,514
  • 53
  • 213
  • 334
1

Something totally not OOP but yet, composition usually means an extra cache-miss. It does depend but having the data closer is a plus.

Generally, I refuse to go into some religious fights, using your own judgment and style is the best you can get.

bestsss
  • 11,796
  • 3
  • 53
  • 63
  • 1
    Actually, you might be surprised what many languages that support composition well do with this. There's a lot of useful tricks you can do at runtime to optimize well above anything you could do in compile-time. Regardless, this is one kind of the bad trade-off Knuth meant when talking about premature optimization - if you can argue that you chose OOP over composition *because of dispatch overhead*... why are you using OOP? Surely there's more of a difference between static dispatch and OOP than between OOP and delegates? – Luaan Jul 16 '15 at 14:47
  • This is an implementation detail. If I write `struct{int i; struct {int j}}` in C, it's still composition and not any more likely to lead to a cache miss. – weberc2 Dec 11 '15 at 23:55
  • 1
    @weberc2, The 1st tag is 'Java'. There is no `struct` (i.e. no headless objects) in Java. You need some `struct *` not just `struct`. While indirections are 'implementation detail' the performance gain/loss is non-trivial. Compare LinkedList to ArrayList for instance. – bestsss Dec 12 '15 at 10:46
  • @Luaan, Java is not amongst those languages (that will save the indirection during composition). Composition also means higher memory footprint and more work for the GC. Don't get me wrong - for anything non-performance critical, I'd frown mindless inheritance... Writing library code/sub milliseconds trading you'd prefer not to pay for the indirections. – bestsss Dec 12 '15 at 10:51
  • Ah, I thought you were talking generally. It's a bummer Java punishes you for following best practices (cache misses, increased work for GC, larger memory footprint, etc). :/ – weberc2 Dec 12 '15 at 23:21
0

You wrote:

[1] Many people use classical inheritance to achieve polymorphism instead of letting their classes implement an interface. The purpose of inheritance is code reuse, not polymorphism. Furthermore, some people use inheritance to model their intuitive understanding of an "is-a" relationship which can often be problematic.

In most languages, the line between 'implementing an interface' and 'deriving a class from another' is very thin. In fact, in languages like C++, if you're deriving a class B from a class A, and A is a class which consists of only pure virtual methods, you are implementing an interface.

Inheritance is about interface reuse, not implementation reuse. It is not about code reuse, as you wrote above.

Inheritance, as you correctly point out, is meant to model an IS-A relationship (the fact that many people get this wrong has nothing to do with inheritance per se). You can also say 'BEHAVES-LIKE-A'. However, just because something has an IS-A relationship to something else doesn't meant that it uses the same (or even similiar) code to fulfill this relationship.

Compare this C++ example which implements different ways to output data; two classes use (public) inheritance so that they can be access polymorphically:

struct Output {
  virtual bool readyToWrite() const = 0;
  virtual void write(const char *data, size_t len) = 0;
};

struct NetworkOutput : public Output {
  NetworkOutput(const char *host, unsigned short port);

  bool readyToWrite();
  void write(const char *data, size_t len);
};

struct FileOutput : public Output {
  FileOutput(const char *fileName);

  bool readyToWrite();
  void write(const char *data, size_t len);
};

Now imagine if this was Java. 'Output' was no struct, but an 'interface'. It might be called 'Writeable'. Instead of 'public Output' you would say 'implements Writable'. What's the difference as far as the design is concerned?

None.

Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
  • I agree with most of what you write. But just because there's no discernible difference between implementing an interface and inheriting from a class with only abstract methods in some languages, that does not provide a compelling reason to use classical inheritance in the rest of the cases, ie. when you extend a class whose methods are *not* abstract. – KaptajnKold Jul 28 '10 at 10:41
  • 1
    What you call `classical inheritance` is most likely actually inappropriate inheritance. It just happens that inheritance is, at least in some languages, the mechanism for implementing an interface. This is no either/or thing. – Frerich Raabe Jul 28 '10 at 14:11
0

When you asked:

Even if you know that classical inheritance is not incorrect to implement a certain model, is that reason enough to use it instead of composition?

The answer is no. If the model is incorrect (using inheritance), than it's wrong to use no matter what.

Here are some problems with inheritance that I've seen:

  1. Always having to test the run time type of derived class pointers to see if they can be cast up (or down too).
  2. This 'testing' can be achieved in various ways. You may have some sort of virtual method that returns a class identifier. Or failing that you may have to implement RTTI (Run time type identification) (At least in c/c++) which can give you a performance hit.
  3. class types that fail to get 'cast' up can be potentially problematic.
  4. There are many ways to cast your class type up and down the inheritance tree.
WW.
  • 23,793
  • 13
  • 94
  • 121
C.J.
  • 15,637
  • 9
  • 61
  • 77
0

Classical inheritance's main usefulness is if you have a number of related classes that will have identical logic for methods that operate on instance variables/properties.

There are really 3 ways to handle that:

  1. Inheritance.
  2. Duplicate the code (code smell "Duplicated code").
  3. Move the logic to yet another class (code smells "Lazy Class," "Middle Man," "Message Chains," and/or "Inappropriate Intimacy").

Now, there can be misuse of inheritance. For example, Java has the classes InputStream and OutputStream. Subclasses of these are used to read/write files, sockets, arrays, strings, and several are used to wrap other input/output streams. Based on what they do, these should have been interfaces rather than classes.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
  • Your third point isn't a very good one. If you move your logic to another class, you will still have to use inheritance. And if you use composition (Traits, Mixins, Interfaces, Abstract Classes) then it's no longer a "code smell". In fact, these are generally preferred over inheritance anyway, since they allow for shared logic without the need for shared state. – yyny Jan 14 '17 at 16:07
0

One of the most useful ways I see to use inheritance is in GUI objects.

Brad Barker
  • 2,053
  • 3
  • 17
  • 28