Technically everything that can be realized with inheritance can be realized with delegation as well. So the answer would be "no".
Transforming inheritance into delegation
Let's say we have the following classes implemented with inheritance:
public class A {
String a = "A";
void doSomething() { .... }
void getDisplayName() { return a }
void printName { System.out.println( this.getDisplayName() };
}
public class B extends A {
String b = "B";
void getDisplayName() { return a + " " + b; }
void doSomething() { super.doSomething() ; ... }
}
The stuff works nicely, and calling printName
on an instance of B will print "A B"
in the console.
Now, if we rewrite that with delegation, we get:
public class A {
String a = "A";
void doSomething() { .... }
void getDisplayName() { return a }
void printName { System.out.println( this.getName() };
}
public class B {
String b = "B";
A delegate = new A();
void getDisplayName() { return delegate.a + " " + b; }
void doSomething() { delegate.doSomething() ; ... }
void printName() { delegate.printName() ; ... }
}
We need to define printName
in B and also to create the delegate when B is instantiated. A call to doSomething
will work in a similar way as with inheritance. But a call to printName
will print "A"
in the console. Indeed with delegation, we lost the powerful concept of "this" being bound to the object instance and base methods being able to call methods that have be override.
This can be solved in the language supports pure delegation. With pure delegation, "this" in the delegate will still reference the instance of B. Which means that this.getName()
will starts the method dispatch from class B. We achieve the the same as with inheritance. This is the mechanism used in prototype-based language such as Self which have delegation has a built-in feature (You can read here how inheritance works in Self).
But Java doesn't have pure delegation. Are when then stuck? No really, we can still do that ourselves with some more effort:
public class A implements AInterface {
String a = "A";
AInterface owner; // replace "this"
A ( AInterface o ) { owner = o }
void doSomething() { .... }
void getDisplayName() { return a }
void printName { System.out.println( owner.getName() };
}
public class B implements AInterface {
String b = "B";
A delegate = new A( this );
void getDisplayName() { return delegate.a + " " + b; }
void doSomething() { delegate.doSomething() ; ... }
void printName() { delegate.printName() ; ... }
}
We are basically re-implementing what the built-in inheritance provides. Does it make sense? No really. But it illustrates that inheritance can always be converted to delegation.
Discussion
Inheritance is characterized by the fact that a base class can call a method that is overridden in a sub class. This is for instance the essence of the template pattern. Such things can not be done easily with delegation. On the other hand, this is exactly what makes inheritance hard to use. It require a mental twist to understand where polymorphic dispatch happen and what is the effect if methods are overridden.
There are some known pitfalls about inheritance and the fragility it may introduce in the design. Especially if the class hierarchy evolves. There can also be some issues with equality in hashCode
and equals
if inheritance is used. But on the other side, it's still a very elegant way to solve some problems.
Also, even if inheritance can be replaced with delegation, one you can argue that they still achieve different purpose and complement each other -- they don't convey the same intention which is not captured by pure technical equivalence.
(My theory is that when somebody starts doing OO, we are tempted to over-use inheritance because it's perceive like a feature of the language. Then we learn delegation which is pattern/approach and we learn to like it as well. After some time, we find a balance between both and develop of sense of intuition of which one is better in which case. Well, as you can see, I still like both, and both deserve some caution before being introduced.)
Some literature
Inheritance and delegation are
alternate methods for incremental
definition and sharing. It has
commonly been believed that delegation
provides a more powerful model. This
paper demonstrates that there is a
“natural” model of inheritance which
captures all of the properties of
delegation. Independently, certain
constraints on the ability of
delegation to capture inheritance are
demonstrated. Finally, a new framework
which fully captures both delegation
and inheritance is outlined, and some
of the ramifications of this hybrid
model are explored.
One of the most intriguing—and at the
same time most problematic—notions in
object-oriented programing is
inheritance. Inheritance is commonly
regarded as the feature that
distinguishes object-oriented
programming from other modern
programming paradigms, but researchers
rarely agree on its meaning and usage. [...]
Because of the strong coupling of classes and the proliferation of unneeded class members induced
by inheritance, the suggestion to use composition and delegation instead has become commonplace.
The presentation of a corresponding refactoring in the literature may lead one to believe that
such a transformation is a straightforward undertaking. [...]