11

This question is NOT question like "inheritence vs composition".

I understand completely how inheritance differs from composition, I know the Liskov substitution principle, the diamond problem, advantages and disadvantages both of them and both concepts seem to be simple. But there is so many questions everywhere about inheritance and composition, that i thought, maybe I misunderstand something in this simple idea.

Lets focus on Go. Go is a language from Google and everybody is excited it has no inheritance, it has no classes, but it has composition and this is cool. For me, the composition in Go gives you exactly the same functionality as inheritance in other languages (C++, Java, ...) - component methods are automatically exposed and available as methods of later structs, like here:

package main

import (
    "fmt"
)

type Car struct{
    name string
}

func (c *Car) move() bool { 
    return true
} 

type MyCar struct{
    Car   
}

func main() {
    var c MyCar
    fmt.Print(c.move())
}

So to sum everything up, composition is better than inheritance because:

  1. is more flexible (allows you to change the component in runtime, so you can affect the way "classes" work.
  2. is free from diamond problem (but diamond problem is solvable, so this is not strong advantage)

And if you consider Go and its interfaces (every object, that has methods defined by an interface, implements this interface implicite) do you have the ultimate solution? Can we say that composition with some syntactic sugar can replace inheritance?

Such design agrees with Liskov substitution principle. Do I miss something or inheritance (known from any language) has no advantages over composition (and interfaces) known from Go?

===== edit1 =====

For clarification, it is possible in Go to use "standard" composition mechanism, like this (this example behaves like the previous one):

package main

import (
    "fmt"
)

type Car struct{
    name string
}

func (c *Car) move() bool { 
    return true
} 

type MyCar struct{
    car Car
}

func (c *MyCar) move() bool { 
    return c.car.move()
} 

func main() {
    var c MyCar
    fmt.Print(c.move())
}

But if you use it like in the previous example, all the methods are available implicite "in MyCar class".

Wojciech Danilo
  • 11,573
  • 17
  • 66
  • 132
  • 1
    You're not far from truth. Maybe this will clear things up: http://en.wikipedia.org/wiki/Composition_over_inheritance – SomeWittyUsername Apr 01 '13 at 18:53
  • 1
    I'm not familiar with Go, but this looks an awful lot like mixins in ruby, which, I believe, are a way of accomplishing multiple inheritance. This does not look like composition in it's true sense (where you would be delegating responsibilities to another object). This confuses your question since it looks like you are comparing two different methods of inheritance. – hifier Apr 01 '13 at 20:21
  • @icepack I have seen this page. It was one of several "articles" my question bases. – Wojciech Danilo Apr 01 '13 at 21:01
  • 1
    @objectiveGeek thats funny, because my example shows **normal** composition but with automatic method promotion (a syntactic sugar). There is no magic in it - you still can access components like this: `var c MyCar; c.Car.move(); /*or the same */ c.move()`. So if this is the same as inheritance to you, then the answer to my question is "yes, you can use composition with some syntactic sugar to replace inheritance" – Wojciech Danilo Apr 01 '13 at 21:04
  • 1
    @danilo2 Inheritance is normally implemented via composition if you go low-level enough. So yes, to be formalistic - you can define a reduction from inheritance to composition thus all the functionality of inheritance can be obtained via composition. The main reason for using inheritance, IMHO, is a better correlation to design (when appropriate, of course). – SomeWittyUsername Apr 01 '13 at 21:22
  • @danilo2 I don't think that the automatic method promotion in Go is just syntactic sugar for composition. The mechanism you demonstrate allows you to treat an instance of the composite object (MyCar) as if it *is* an instance of the "super" type (car). This is a form of inheritance IMO. The inheritance vs composition conversation is usually about how best to share behavior. i.e. Should you factor the common methods/state into a super class or delegate them to another object? But when using composition we wouldn't necessarily duplicate the interface in a delegate and proxy the calls 1:1. – hifier Apr 01 '13 at 22:17
  • @objectiveGeek you are not completely right. In go (in particular in this example) I cannot use `MyCar` as if it is an instance of `Car`. If you pass `MyCar` instance to a function accepting `Car`, you get an error. I understeand all that conversations and I was wondering if we can replace both use cases with a single mechanism :) – Wojciech Danilo Apr 01 '13 at 22:22
  • @icepack that is very interesting - do you have any further informations about such low-level reduction from inheritance to composition? – Wojciech Danilo Apr 01 '13 at 22:25
  • possible duplicate of [Is Inheritance really needed?](http://stackoverflow.com/questions/278476/is-inheritance-really-needed) – nawfal Oct 03 '13 at 06:53
  • or [is-there-anything-composition-cannot-accomplish-that-inheritance-can](http://stackoverflow.com/questions/2238642/is-there-anything-composition-cannot-accomplish-that-inheritance-can) **or** [why-use-inheritance-at-all](http://stackoverflow.com/questions/3351666/why-use-inheritance-at-all?lq=1) – nawfal Oct 03 '13 at 06:54

5 Answers5

7

The Short Answer

It's really not as black and white as that. In short, yes. Any situation that can be solved with inheritance can be solved, near enough, by composition. So in short, the answer to your question is yes; inheritance can be replaced by composition.

Why it's not that simple

When to use Inheritance
It's not a matter of whether you CAN swap them out. It depends on the context that you're programming in, and it becomes more of a question of whether you SHOULD swap them out. Take this simple example in Java:

public class Person
{
    // Assume every person can speak.
    public void speak()
    {
    }
}

Now, let's say we have another class, Dave. Dave IS a person.

public class Dave extends Person
{
     public void speak() { System.out.println("Hello!"); }
     public void killSomeone() {} // Dave is a violent Guy.
}

Now would it make more sense for the class Dave to look like this?

public class Dave
{
     private Person p;
     // Composition variant.

     public void speak() { p.speak(); }
     public void killSomeone() {} // Dave is a violent Guy.
}

This code implies Dave has a person. It's not as simple and doesn't explain itself as well. Also, anything a Person can do, Dave can do, so it makes sense that we assert Dave is a "Person".

When to use Composition

We use Composition when we only want to expose part of the class' interface. Following our previous example, let's say Dave has a Guitar. The guitar has a more complex interface:

public class Guitar
{
     public Color color;
     // Guitar's color.
     public Tuning tuning;
     // Guitar's tuning.

     public void tuneGuitar()
     {}

     public void playChord()
     {}

     public void setColor()
     {}
}

Now, if we were to inherit this class, what would the outcome be?

Well, class Dave would now have attributes color and tuning. Does Dave have a tuning? I think not! This is where inheritance makes no sense. We don't want to expose the entire Guitar interface along with the Dave interface. We only want the user to be able to access what Dave needs to access, so in this case we would use some composition:

public class Dave extends Person
{
     private Guitar guitar;
     // Hide the guitar object. Then limit what the user can do with it.

     public void changeGuitarColor(Color newColor)
     {
         // So this code makes a lot more sense than if we had used inheritance.
         guitar.setColor(newColor);
     }


     public void speak() { System.out.println("Hello!"); }
     public void killSomeone() {} // Dave is a violent Guy.
}

Conclusion

It's really not a case of what can replace the other. It's about the situation that you are implementing the techniques in. Hopefully, by the end of the example you'll see that inheritance is for situations where one object IS A object, and composition is used when one object HAS A object.

christopher
  • 26,815
  • 5
  • 55
  • 89
  • Chris I very appreciate your answer, but your answer is language syntax specyfic - please see my example. I understand *is a* and *has*, but using some special syntax, like in Go, we can mimic both behaviors with composition. You can get used to the Go syntax and see that MyCar **is** a Car if Car is in list of its "components" - but this is only syntax and apperance - it could be improoven. We can use in `Go` "normal" composition, as you have shown here it the components are named (in my example, the `Car` is name of a type and it is called an `unnamed component` or `unnamed variable`) – Wojciech Danilo Apr 01 '13 at 19:35
  • I simply used Java as an example, because it's the language I am most familiar with and I knew I could explain the concept better with it. I'm sorry, I don't completely understand your comment. – christopher Apr 01 '13 at 19:39
  • Please look at edited question and additional example. Sorry for being not clear to you. I was trying to say, that you are talking about apperance of things (something looks like or something is like something else). This apperance is strongly connected with syntax. I dont want to talk about specific language (this should be language agnostic question). In Go inheritance is replaced by composition and special syntax allowing promoting methods of the components. I wanted to know if it is a "silver bullet" or it is weaker in some cases than standard inheritance. – Wojciech Danilo Apr 01 '13 at 20:59
  • 2
    @danilo2 I think your question is just a language-specific to Go and ChrisCooney's answer is language-specific to Java. We all have to code in something, and if that something doesn't have the Go-like feature you described then there is a big reason to use inheritance in many instances. I don't think you can separate language from the question as easily as you'd like. – tcarvin Apr 02 '13 at 20:55
  • I tried not to be language specyfic, because I'm developing right now my own language (a little bit more declarative and reactive, but that is not important right now) and I am considering to abandon inheritance in favor of some kind of composition. I hope now, you understeand, why I dont want to e "language specific". – Wojciech Danilo Apr 02 '13 at 23:18
4

Sorry for necroposting, but it seems that the question and the answers concentrate on code reuse. We can use both inheritance and composition to reuse some code from the common "ancestor", it's true. And composition works better here.

But inheritance is primarily not for code reuse, it's for dynamic binding. The "is a" relationship can be practically formulated as follows: calling code is using interface of the object and knows nothing about particular implementation.

Pseudocode:

// Interface
class A { 
  drawMe() {} ; 
};
// Implementations
class Rect:A { 
  drawMe() {DrawRect();}; 
};
class Circle:A { 
  drawMe() {Drawcircle();}; 
};

main() {
  // We fill the array in one part of the program
  Array_of_A arr;
  arr.add(new Rect);
  arr.add(new Circle);
  // We can use the array in completely another part
  // without any idea of what the items really are,
  // only know the interface
  foreach(item from arr) {
     item->drawMe();
  }
}

In many languages (e.g. like C++) inheritance is the only practical way to say "this object implements this interface". And also it allows to do some things like code reuse, which really are better done with composition.

I know nothing of Go, but I understand your words correctly, it offers another way of defining "this object implements this interface":

every object, that has methods defined by an interface, implements this interface implicite

So if you also can call the objects by interface, it does the work of inheritance. But it additionally allows the substitution of the base class, which is why I think they call it composition. And maybe because of it being internally implemented in some way other than vtable, but I can't think of where it can make any difference.

So, inheritance can be replaced by composition if you find a way to say "this object implements this interface".

Steed
  • 1,292
  • 1
  • 14
  • 33
3

Nice question ...

You may want to prefer inheritance over composition when you want to distinguish semantically between "A is a B" and "A has a B". E.g. class Car may have an Engine member (composition), but may be (i.e. inherit from) a Vehicle.

I think the distinction plays out in having to maintain the number of methods shared by your two classes. When you inherit, you only need to override those (virtual) functions in the base class that you really need to; if you were to use purely composition, you'd need to re-implement every method of your member class that's public.

Ultimately, the "best" method is the one that is most suitable for your current application.

Edit:

There's a small but succinct debate about it here: http://www.sitepoint.com/forums/showthread.php?568744-When-to-use-inheritance

as well as a Wikipedia article(!) about it: http://en.wikipedia.org/wiki/Composition_over_inheritance#Drawbacks

maditya
  • 8,626
  • 2
  • 28
  • 28
  • Thanks, I know this disadventage, but please look at Go - if you use composition, you do not need to rewrite every method, because all methods are propagated automatically - please look at my example. – Wojciech Danilo Apr 01 '13 at 19:31
  • 1
    Sorry, I was slightly sloppy reading your question. I guess you're asking, "Is the composition offered by Go a better solution than separate inheritance and composition in other languages?" I don't know ... To me, it looks like mixins offer pretty much the same functionality, at essentially the same amount of effort as the composition example you presented up there – maditya Apr 01 '13 at 20:05
  • Not exactly - I'm writing my own programming language and I'm considering abandon inheritance in favor of composition. So the question is completely language agnostic. I do not want to compare Go vs Java mechanisms - I'm talking about **any** language (this can be in particular Go), so if the composition in Go is as good as inheritance in other languages, than yes, it is possbile to completely replace inheritance by composition **in general**. – Wojciech Danilo Apr 01 '13 at 20:12
  • I don't know about that ... the composition in Go is, as you yourself point out, somewhat different from what is thought of as composition in other languages ... so to me it's more accurate to say that "it is possible to completely replace inheritance by **the type of composition offered by Go**" – maditya Apr 01 '13 at 20:18
  • Composition in Go is normal composition with some syntactic sugar to implicit promote methods of components. There is no magic - only special syntax. – Wojciech Danilo Apr 01 '13 at 21:00
  • So then my short answer is "yes". :) – maditya Apr 01 '13 at 21:09
2

Down to the core inheritance is just a convenience-mechanism in high-level languages that implement branching (dispatching) on types. Therefore, all special mechanisms related to inheritance and subtyping-polymorphism can be solved by adding explicit "type tags" and branching on them.

In Java, where sometimes tree-only polymorphism does not model real-world problems well, it is ubiquitous to match on types (instanceof or pattern matching etc.). You can build your own type tags with composition to achieve the same thing. In fact, due to the inefficiency of enumerations in Java, we also handmake enums as constants, too.

The real question is about ergonomics. Software construction is all about handling complexity. If you can reduce the level of complexity using inheritance, i.e., the new entity is really an extension to and old one, then why not use inheritance? After all, if "can do" is really the question, we would be still writing machine code now. The reason why those high-level mechanisms exist is to help us understand the question better. To this degree, I do not think that replacing inheritance with composition without condition will do us any good. It will only add more complexity and boilerplate code to our project, to no good.

Seideun
  • 153
  • 2
  • 7
1

I think the real question here is inheritance vs. polymorphism. In popular languages like Java the two are combined, i.e. subtype polymorphism is only achieved through implementation inheritance. Go proves that polymorphism can be achieved without inheritance, even in a statically-typed language (and this was known before Go). So the question is, if you can have polymorphism without inheritance, why would you want it with inheritance?

The modern answer seems to be... you wouldn't. Conflating inheritance with polymorphism assumes inheritance is the most common use case. Even James Gosling admits that implementation inheritance was a mistake. That isn't to say it's useless; but the use cases for inheritance could be covered by a framework or DSL rather than forced into every subtype relationship. In this regard, Go had the opportunity to learn from Java's mistake.

jaco0646
  • 15,303
  • 7
  • 59
  • 83