CSC/ECE 517 Fall 2007/wiki2 10 cv
Inheritance vs. delegation. Follow the debate on inheritance vs. delegation. Construct (or, better, cite) examples that show cases where inheritance is better, and cases where delegation is better. Attempt to characterize the situations in which you should employ one or the other.
Inheritance
Inheritance is a way to form new classes in object oriented programming using already defined classes. Inheritance is used to help reuse code that already exists with little or no modifications and this is one of the advantages of using inheritance since it helps reduce the complexity of a program. The inherited class is called the super class and new class is called the Derived Class. Here, the derived class can use the attributes and behavior of the super class and hence Inheritance is used when the derived class is a type of Super Class. In other terms, the derived class has all the properties and behavior of the super class plus some other special behaviors and attributes. Many programmers are confused on when to use inheritance but inheritance is mainly used when a programmers new class can be used in place of the existing class and the relationship between them can be described as an is-a relationship.
Advantages of Inheritance
- Avoids rewriting the code when the functionality is already present
- Categorizes the code well into well defined reusable logical blocks(Classes)
- Inheritance enables overriding methods therefore allows polymorphism
Disadvantages of Inheritance
- Exposes a subclass to the details of its parent class
- Changes in the parent class implementation would cause the subclass to change as well
- Inheritance is static, that is the hierarchy of an object is defined at compile time and it can not be changed at runtime.
Delegation
Delegation is when one object relies on another object in order to provide a specified set of functionalities and this is sometimes referred to as aggregation, consultation, or forwarding. It is better to use delegation when a programmer's new class needs to use some of the existing class functionality and the relationship can be described as a has-a or uses-a relationship. The following example describes how delegation is different from Inheritance:
class A { void foo() { this.bar() // "this" is also known under the names "current" and "self" in other languages }
void bar() { print("a.bar") } }
class B { delegationlink A a void foo() { a.foo() // call foo() on the a-instance }
void bar() { print("b.bar") } }
a = new A() b = new B(a) // establish delegation between two objects
Calling b.foo() will result in b.bar to be printed on the screen. Using normal Inheritance where Class B would inherit Class A, the result would have been a.bar. This happens because, when a.foo() is called from inside foo() of class B, it is also passed the reference to the "this" pointer of class B. Therefore, when method foo() of class A tries to call this.Bar(), it refers to the Bar() method of Class B, instead of Class A.
Advantages of Delegation
- Provides flexibility due to the fact that any object can be replaced at run time by another one of the same type
- Appears a more natural concept than Inheritance as its much more local and hence effects a specific part of the class
Advantages of Delegation
- Delegation is not statically type checked, therefore can give rise to bugs
Examples of Delegation and Inheritance
The following section discusses the examples explaining the usage of Inheritance and Delegates and how they can be used in specific situations. Also, it talks about the pros and cons of using these models by taking a common example.
Where Delegation makes more sense than Inheritance
The Game Example
Consider a game with different difficulty levels. Now suppose we have two kind of player levels smart and dumb. Here the requirement is that it is possible to change the difficulty level of the game at any time. We can construct two models to solve this problem, one with inheritance and the other with delegation.
Inheritance Model
In model A, there are two classes namely "Dumb Player" and "Smart Player" which inherits from the Player Abstract Class. The client of the computer player must know when/how to create the instances of an appropriate class when switching from difficult to simple mode or vice versa. The trouble here is that in Inheritance, once the object instance is created its type can not be changed at later time.
Client code to change the difficulty level at run-time is very complicated, and requires detailed knowledge of the computer player’s implementation classes.
Delegation Model
On the other hand in model B, it is possible for class ComputerPlayer to delegate to GameStrategy Interface and also have a simple setDifficulty() method. Whenever the difficulty changes via setDifficulty() method, the getMove() method can be delegated to GameStrategy Interface which allows two more classes called SmartStrategy and DumbStrategy to inherit from it, which themselves implement their versions of getMove(). Hence, for any difficulty level everytime the correct getMove() function is called via delegation. This can be done with delegation and not with inheritance since delegation is a dynamic relationship, providing a different kind of runtime flexibility in the code, compared to inheritance.
Where Inheritance makes more sense than Delegation
A Window Class Example
Inheritance is generally used when an object derives all of the properties of the base object. This is done at compile time and hence cannot be changed at runtime. Inheritance is fundamentally used when the derived class "is a type" of the super class. In this case the derived class is a specialized set of the super class containing all the members of the super class plus its own specialized members. Whereas we use delegation where an object would like to rely upon another object to provide a set of functionalities.
Consider a Window class, where it implements methods like Open(), Close(), Minimize(), Maximize(), Restore(), Move(). Now suppose we create another class called BrowserWindow which inherits the Window Class. This new class is a window but a special kind of window which along with the general methods (like Open,Close) also implements methods like SaveNClose(), ExitSession(), LifeTime() etc. So, in this case its valid for BrowserWindow class to inherit from Window super class.
Now, here we can make use of delegation. Consider the function SaveNClose(). In this function the normal behavior would be close the window(in case there is no data to save), but suppose we also need to perform some other operations like saving the session or asking the user if he wants to close all of the tabs inside the window, then BrowserWindow class can delegate this functionality to another class, say UserSession. This way the BrowserWindow class does'nt have to bother about operations that should be performed on user data/session while closing the window. Note that this can only be done with the help of delegation, not inheritance. This is because, BrowserWindow is not a UserSession and hence it should not inherit UserSession class. Instead it can delegate its SaveNClose() method so that UserSession class can can perform checks on User session.
Hence, it makes more sense to use Inheritance between Window Class and BrowserWindow Class whereas between BrowserWindow and UserSession delegation should be used.
References
Inheritance vs. Delegation
Practices of an Agile Developer
Delegation
Systems Analysis and Design
http://forum.java.sun.com/thread.jspa?threadID=702260&messageID=4072925
http://www.perlmonks.org/index.pl?node_id=278375