Inheritance vs Delegation
上一篇 /
下一篇 2014-09-02 11:16:36
/ 个人分类:Java
Found this very good explanation here
http://www.jguru.com/faq/view.jsp?EID=27916
Both delegation and inheritance are important
concepts in object-oriented software design,
but not everyone would label them as patterns.
In particular, the seminal book on design
patterns by the “Gang of Four” contains
a discussion of inheritance and delegation, but
the authors do not treat these topics as
specific patterns. It is reasonable to think
of them as design concepts which are more
general than specific design patterns.
Inheritance is a relationship between two classes
where one class, called a subclass in this
context, inherits the attributes and operations
of another class, called its superclass.
Inheritance can be a powerful design/reuse
technique, especially when it is used in the
context of the Liskov Substitution Principle.
(The article by Robert Martin at
http://www.objectmentor.com/publications/lsp.pdf
provides an excellent explanation of the ideas
behind Barbara Liskov’s original paper on
using inheritance correctly.) The primary
advantages of inheritance are
- it is directly supported by object-oriented
languages, and
- it provides the context for polymorphism in
strongly-typed object-oriented languages
such as C++ and Java.
But since the inheritance relationship is defined
at compile-time, a class can’t change its
superclass dynamically during program execution.
Moreover, modifications to a superclass
automatically propagate to the subclass,
providing a two-edged sword for software
maintenance and reuse. In summary, inheritance
creates a strong, static coupling between a
superclass and its subclasses.
Delegation can be viewed as a relationship
between objects where one object forwards certain
method calls to another object, called its
delegate. Delegation can also a powerful
design/reuse technique. The primary advantage
of delegation is run-time flexibility –
the delegate can easily be changed at run-time.
But unlike inheritance, delegation is not
directly supported by most popular
object-oriented languages, and it doesn’t
facilitate dynamic polymorphism.
As a simple example, consider the relationship
between a Rectangle class and a Window class.
With inheritance, a Window class would inherit
its
rectangular properties from class
Rectangle. With delegation, a Window object
would maintain a reference or pointer to a
Rectangle object, and calls to rectangle-like
methods of the Window object would be delegated
to corresponding methods of the Rectangle object.
Now let’s consider a slightly more complex
example. Suppose employees can classified based
on how they are paid; e.g., hourly or salaried.
Using inheritance, we might design three classes:
an Employee class which encapsulates the
functionality common to all employees, and two
subclasses HourlyEmployee and SalariedEmployee
which encapsulates pay-specific details. While
this design might be suitable for some
applications, we would encounter
problems in a scenario where a person changes,
say from hourly to salaried. The class of an
object and the inheritance relationship are both
static, and objects can’t change their
class easily (but see the State pattern for
tips on how to fake it).
A more flexible design would involve delegation
– an Employee object could delegate
pay-related method calls to an object whose
responsibilities focused solely on how the
employee is paid. In fact, we might still use
inheritance here in a slightly different manner
by creating an abstract class (or interface)
called PayClassification with two subclasses
HourlyPayClassification and
SalariedPayClassification which implement
classification-specific computations. Using
delegation as shown, it would be much easier
to change the pay classification of an
existing Employee object.
This second example illustrates an important
point: In implementing delegation, we often
want the capability to replace the delegate with
another object, possibly of a different class.
Therefore delegation will often use inheritance
and polymorphism, with classes of potential
delegates being subclasses of an abstract
class which encapsulates general delegate
responsibilities.
One final point. Sometimes, the choice between
delegation and inheritance is driven by external
factors such as programming language support
for multiple inheritance or design constraints
requiring polymorphism. Consider threads in
Java. You can associate a class with a thread
in one of two ways: either by extending
(inheriting) directly from class Thread, or by
implementing the Runnable interface and then
delegating to a Thread object. Often the
approach taken is based on the restriction
in Java that a class can only extend one class
(i.e., Java does not support multiple
inheritance). If the class you want to
associate with a thread already extends some
other class in the design, then you would have
to use delegation; otherwise, extending class
Thread would usually be the simpler approach.
收藏
举报
TAG: