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:
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".
One more benefit of composition over inheritance is testing scope. Unit testing is easy in composition because we know what all methods we are using from another class. We can mock it up for testing whereas in inheritance we depend heavily on superclass and don't know what all methods of superclass will be used.
Composition is in contrast to inheritance, it enables the creation of complex types by combining objects (components) of other types, rather than inheriting from a base or parent class. To put it simply, composition contains instances of other classes that implement the desired functionality.
Delegation can be an alternative to inheritance. Delegation means that you use an object of another class as an instance variable, and forward messages to the instance.
Prefer composition over inheritance as it is more malleable / easy to modify later, but do not use a compose-always approach. With composition, it's easy to change behavior on the fly with Dependency Injection / Setters. Inheritance is more rigid as most languages do not allow you to derive from more than one type.
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.
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.
}
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.
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".
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With