CSC/ECE 517 Fall 2007/wiki2 10 c4: Difference between revisions
(24 intermediate revisions by the same user not shown) | |||
Line 27: | Line 27: | ||
* Inheritance should be restricted to objects of the same type.[3] | * Inheritance should be restricted to objects of the same type.[3] | ||
* When the base class is to general but the functionality is still needed. | |||
=== When to use Delegation=== | === When to use Delegation=== | ||
Line 44: | Line 46: | ||
===Example 1=== | ===Example 1=== | ||
Inheritance is better in this example because any specific account type will require the basic attributes of an account. An interest bearing account also "is a" account. Delegation would not be great in this case because allowing for methods to be determined dynamically opens up opportunities for hacker and calculation issues. Example below is from link [7] and link [8]. | |||
public class Account { | public class Account { | ||
Line 71: | Line 75: | ||
class InterestBearingAccount extends Account | class InterestBearingAccount extends Account{ | ||
{ | private static double default_interest = 7.95; | ||
private double interest_rate; | |||
// Overloaded constructor accepting balance and an interest rate | |||
public InterestBearingAccount( double amount, double interest){ | |||
balance = amount; | |||
interest_rate = interest; | |||
} | |||
// Overloaded constructor accepting balance with a default interest rate | |||
public InterestBearingAccount( double amount ){ | |||
balance = amount; | |||
interest_rate = default_interest; | |||
} | |||
// Overloaded constructor with empty balance and a default interest rate | |||
public InterestBearingAccount(){ | |||
balance = 0.0; | |||
interest_rate = default_interest; | |||
} | |||
public void add_monthly_interest(){ | |||
// Add interest to our account | |||
balance = balance + | |||
(balance * interest_rate / 100) / 12; | |||
} | |||
} | |||
===Example 2=== | |||
Here is another example where inheritance is better than delegation. The generalized shape interface is used as a basis for all of the subclasses. | |||
Notice that each subclass is designed to personal specifications for the object. Here there would be no need for any of the code to dynamically change. Example below is from link [9]. | |||
public interface Shape{ | |||
public double getArea(); | |||
public double getPerimeter(); | |||
} | |||
public class Rectangle implements Shape | |||
{ | |||
private int width; | |||
private int height; | |||
public Rectangle(){ | |||
this(1,1); | |||
} | |||
public Rectangle(int width, int height){ | |||
this.width = width; | |||
this.height = height; | |||
} | |||
public int getWidth(){ | |||
return this.width; | |||
} | |||
public int getHeight(){ | |||
return this.height; | |||
} | |||
public double getPerimeter(){ | |||
return 2 * this.height + 2 * this.width; | |||
} | |||
public double getArea(){ | |||
return width * height; | |||
} | |||
public String toString(){ | |||
return "width: " + this.width + ", height: " + this.height; | |||
} | |||
} | |||
public class Square extends Rectangle{ | |||
public Square(int lengthOfSide){ | |||
super(lengthOfSide, lengthOfSide); | |||
} | |||
public int getSide(){ | |||
return getWidth(); | |||
} | |||
public String toString(){ | |||
return "Length of Side: " + getSide(); | |||
} | |||
} | |||
public class Circle implements Shape | |||
{ | |||
private int radius; | |||
public Circle(int radius){ | |||
this.radius = radius; | |||
} | |||
public double getArea(){ | |||
return Math.PI * this.radius * this.radius; | |||
} | |||
public double getPerimeter(){ | |||
return 2 * Math.PI * this.radius; | |||
} | |||
} | } | ||
==Delegation is Better== | |||
===Example 1=== | |||
Delegation is better in this example because class Student doesnt know if it wants to use class Classroom or class Cafeteria's implementation of the f and g methods. During the running of the code class Student can change which class implementation of the functions it points to by calling toClassroom or toCafeteria. Students go between classrooms, libraries, and the cafeteria pretty often throughout a day, delegation allows for an easy change betewen these locations. Inheritance isnt able to handle this dynamically. Any implementation of the code would have to be either in the current class or its parent. It couldnt be in a sibling class. Example below is from link [11]. I have adapted it so that it is more clear to understand. SchoolLocation = I, A = Classroom, B = Cafeteria, C = Student; | |||
interface SchoolLocation { | |||
void f(); | |||
void g(); | |||
} | |||
class Classroom implements School { | |||
public void f() { System.out.println("A: doing f()"); } | |||
public void g() { System.out.println("A: doing g()"); } | |||
} | |||
class Cafeteria implements School { | |||
public void f() { System.out.println("B: doing f()"); } | |||
public void g() { System.out.println("B: doing g()"); } | |||
} | |||
class Sudent implements School { | |||
// delegation | |||
SchoolLocation location = new Classroom(); | |||
public void f() { location.f(); } | |||
public void g() { location.g(); } | |||
// normal attributes | |||
void toClassroom() { location = new Classroom(); } | |||
void toCafeteria() { location = new Cafeteria(); } | |||
} | |||
===Example 2=== | |||
Below is the link to a great example of how to use delegation for a real world scenario. It isn't code but is in the form of diagrams. | |||
This link uses a school registration system as an example. The school registration system consists of students and faculty. This is then broken down further into graduate and undergraduate students. Graduate students can be phd or master students. Some graduate students can also teach classes and be faculty. This brings up a situation where a graduate student needs to inherit from two places. Many know that multiple inheritance isn't a good dway to handle this. The example uses an delegation and interfaces to handle this issue. | |||
http://web.cs.wpi.edu/~gpollice/cs4233-a05/CourseNotes/maps/class7/Exampleofdelegation.html | |||
http://web.cs.wpi.edu/~gpollice/cs4233-a05/CourseNotes/maps/class7/Addingcomplexity.html | |||
http://web.cs.wpi.edu/~gpollice/cs4233-a05/CourseNotes/maps/class7/Crossingboundaries.html | |||
==References== | ==References== | ||
Line 117: | Line 233: | ||
# http://www.softwarefederation.com/csci4448/courseNotes/05_ObjectOrientedDesign.pdf | # http://www.softwarefederation.com/csci4448/courseNotes/05_ObjectOrientedDesign.pdf | ||
# http://www.javaworld.com/javaworld/javaqa/2001-09/01-qa-0914-delegate.html | # http://www.javaworld.com/javaworld/javaqa/2001-09/01-qa-0914-delegate.html | ||
# http://www.javacoffeebreak.com/java102/Account.java | |||
# http://www.javacoffeebreak.com/java104/java104.html | |||
# http://www.cs.utexas.edu/~scottm/cs305j/codingSamples.htm | |||
# http://www.tanguay.info/web/codeExample.php?id=492 | |||
# http://en.wikipedia.org/wiki/Delegation_pattern | |||
# http://web.cs.wpi.edu/~gpollice/cs4233-a05/CourseNotes/maps/class7/Exampleofdelegation.html |
Latest revision as of 15:39, 29 October 2007
Introduction
Problem
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 the process of one class having access to another class's attributes. Inheritance occurs when a class, also called the superclass, is created with generalized methods and attributes, and then another class is created as a subclass to the first class. The subclass provides provides detailed methods and attributes and automatically has access to methods and data members of the superclass. These subclasses can also override the generalized methods of the super class. Sometimes subclasses inherit from more than one super class; the occurrance of this is naturally called multiple inheritance.[1]
Delegation
Delegation is the process of assigning the implementation of a method, within a class, to another method. Generally, the implementation responsibility is forwarded to the parent class. If the parent class can not handle the implementation responsibility, it forwards it to its parent and so on and so on. This forwarding allows a class to dynamically change by changing the parent class relations. Delegation is also called dynamic inheritance.[2]
Inheritance vs Delegation
Inheritance and delegation are used in different situations in object oriented programming. Although they can be used simultaneously, its rarely done due to the difficulty in it. Most of the time people use them interchangeably but are doing so incorrectly.
When to use Inheritance
- Inheritance is used when two objects are of the same type but one of the objects needs to handle somethings differently. The second object would inherit from the first and simply rewrite the code needed in the second object.[3]
- Inheritance is used in is-a relationships between objects. [3]
- Inheritance is used to sub categorize objects.[3]
- Inheritance should be restricted to objects of the same type.[3]
- When the base class is to general but the functionality is still needed.
When to use Delegation
- Delegation is used when two objects aren't of the same type but one has methods and attributes that the other wants to use internally.[3]
- Delegation is used in has-a relationships where the type of object that is included may change during runtime.
- Delegation is used when methods implementation needs to be handled by some other class within the parent tree. The class that will handle the method isn't known right away. [6]
- When code execution within objects needs to be determined dynamically.
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 is Better
Example 1
Inheritance is better in this example because any specific account type will require the basic attributes of an account. An interest bearing account also "is a" account. Delegation would not be great in this case because allowing for methods to be determined dynamically opens up opportunities for hacker and calculation issues. Example below is from link [7] and link [8].
public class Account {
protected double balance; // Constructor to initialise balance public Account( double amount ) { balance = amount; } // Overloaded constructor for empty balance public Account() { balance = 0.0; } public void deposit( double amount ) { balance += amount; } public double withdraw( double amount ) { // See if amount can be withdrawn if (balance >= amount) { balance -= amount; return amount; } else // Withdrawal not allowed return 0.0; } public double getbalance() { return balance; }
}
class InterestBearingAccount extends Account{
private static double default_interest = 7.95; private double interest_rate;
// Overloaded constructor accepting balance and an interest rate public InterestBearingAccount( double amount, double interest){ balance = amount; interest_rate = interest; } // Overloaded constructor accepting balance with a default interest rate public InterestBearingAccount( double amount ){ balance = amount; interest_rate = default_interest; } // Overloaded constructor with empty balance and a default interest rate public InterestBearingAccount(){ balance = 0.0; interest_rate = default_interest; }
public void add_monthly_interest(){ // Add interest to our account balance = balance + (balance * interest_rate / 100) / 12; }
}
Example 2
Here is another example where inheritance is better than delegation. The generalized shape interface is used as a basis for all of the subclasses. Notice that each subclass is designed to personal specifications for the object. Here there would be no need for any of the code to dynamically change. Example below is from link [9].
public interface Shape{
public double getArea(); public double getPerimeter();
}
public class Rectangle implements Shape
{
private int width; private int height; public Rectangle(){ this(1,1); } public Rectangle(int width, int height){ this.width = width; this.height = height; } public int getWidth(){ return this.width; } public int getHeight(){ return this.height; } public double getPerimeter(){ return 2 * this.height + 2 * this.width; } public double getArea(){ return width * height; } public String toString(){ return "width: " + this.width + ", height: " + this.height; }
}
public class Square extends Rectangle{
public Square(int lengthOfSide){ super(lengthOfSide, lengthOfSide); } public int getSide(){ return getWidth(); } public String toString(){ return "Length of Side: " + getSide(); }
}
public class Circle implements Shape
{
private int radius;
public Circle(int radius){ this.radius = radius; } public double getArea(){ return Math.PI * this.radius * this.radius; } public double getPerimeter(){ return 2 * Math.PI * this.radius; }
}
Delegation is Better
Example 1
Delegation is better in this example because class Student doesnt know if it wants to use class Classroom or class Cafeteria's implementation of the f and g methods. During the running of the code class Student can change which class implementation of the functions it points to by calling toClassroom or toCafeteria. Students go between classrooms, libraries, and the cafeteria pretty often throughout a day, delegation allows for an easy change betewen these locations. Inheritance isnt able to handle this dynamically. Any implementation of the code would have to be either in the current class or its parent. It couldnt be in a sibling class. Example below is from link [11]. I have adapted it so that it is more clear to understand. SchoolLocation = I, A = Classroom, B = Cafeteria, C = Student;
interface SchoolLocation {
void f(); void g(); } class Classroom implements School { public void f() { System.out.println("A: doing f()"); } public void g() { System.out.println("A: doing g()"); } } class Cafeteria implements School { public void f() { System.out.println("B: doing f()"); } public void g() { System.out.println("B: doing g()"); } } class Sudent implements School { // delegation SchoolLocation location = new Classroom(); public void f() { location.f(); } public void g() { location.g(); } // normal attributes void toClassroom() { location = new Classroom(); } void toCafeteria() { location = new Cafeteria(); } }
Example 2
Below is the link to a great example of how to use delegation for a real world scenario. It isn't code but is in the form of diagrams. This link uses a school registration system as an example. The school registration system consists of students and faculty. This is then broken down further into graduate and undergraduate students. Graduate students can be phd or master students. Some graduate students can also teach classes and be faculty. This brings up a situation where a graduate student needs to inherit from two places. Many know that multiple inheritance isn't a good dway to handle this. The example uses an delegation and interfaces to handle this issue.
http://web.cs.wpi.edu/~gpollice/cs4233-a05/CourseNotes/maps/class7/Exampleofdelegation.html
http://web.cs.wpi.edu/~gpollice/cs4233-a05/CourseNotes/maps/class7/Addingcomplexity.html
http://web.cs.wpi.edu/~gpollice/cs4233-a05/CourseNotes/maps/class7/Crossingboundaries.html
References
- http://searchsmb.techtarget.com/sDefinition/0,,sid44_gci212351,00.html
- http://www.ccs.neu.edu/research/demeter/papers/context-journal/node3.html
- http://www.tek-tips.com/viewthread.cfm?qid=372254
- http://www.python.org/ftp/python/doc/delegation.ps
- http://www.softwarefederation.com/csci4448/courseNotes/05_ObjectOrientedDesign.pdf
- http://www.javaworld.com/javaworld/javaqa/2001-09/01-qa-0914-delegate.html
- http://www.javacoffeebreak.com/java102/Account.java
- http://www.javacoffeebreak.com/java104/java104.html
- http://www.cs.utexas.edu/~scottm/cs305j/codingSamples.htm
- http://www.tanguay.info/web/codeExample.php?id=492
- http://en.wikipedia.org/wiki/Delegation_pattern
- http://web.cs.wpi.edu/~gpollice/cs4233-a05/CourseNotes/maps/class7/Exampleofdelegation.html