Algorithms and OOD (CSC 207 2014F) : EBoards
Primary: [Front Door] [Schedule] - [Academic Honesty] [Disabilities] [Email] - [Learning Outcomes] [FAQ] [Teaching & Learning] [Grading] [Rubric] - [Calendar]
Current: [Assignment] [EBoard] [Lab] [Outline] [Reading]
Sections: [Assignments] [EBoards] [Examples] [Handouts] [Labs] [Outlines] [Readings]
Reference: [Student-Curated Resources] [Java 8 API] [Java 8 Tutorials] [Code Conventions]
Related Courses: [CSC 152 2006S (Rebelsky)] [CSC 207 2014S (Rebelsky)] [CSC 207 2014F (Walker)] [CSC 207 2011S (Weinman)]
Misc: [Submit Questions] - [SamR] [Glimmer Labs] [CS@Grinnell] [Grinnell] - [Issue Tracker (Course)] [Issue Tracker (Textbook)]
Overview
I've heard some questions about the @Overrides directive, so we'll talk
a bit about it.
Wednesday's lab highlighted some differences in programming style between Prof. Rebelsky and Prof. Walker. We'll talk through those differences by looking at four approaches.
Code
public class Counter
{
int val;
int origin;
public Counter(int origin)
{
this.origin = origin;
this.val = origin;
} // Counter(int)
public void increment()
{
++this.val;
} // increment
public void get()
{
return this.val;
} // get()
public void reset()
{
this.val = this.origin;
} // reset()
public String toString()
{
return "[" + this.val + "]";
} // toString
} // class Counter
Incompletely specified problem: Count twice as fast. At least four possible approaches.
public class DoubleCounterOne
extends Counter
{
public DoubleCounterOne(int origin)
{
super(origin);
} // DoubleCounterOne
@Override
public void increment()
{
this.val += 2;
} // increment
} // DoubleCounter
Nice and small, but requires that you can access a field of the parent class. You might not be able to access that field for one of the following reasons:
private in the parent.We can do something very similar without accessing fields, taking
advantage of the public increment method.
public class DoubleCounterTwo
extends Counter
{
public DoubleCounterTwo(int origin)
{
super(origin);
} // DoubleCountertTwo
@Override
public void increment()
{
super.increment();
super.increment();
} // increment
} // DoubleCounterTwo
But what if we want to be able to "double" an existing counter? How Sam thinks about it: If we're doubling an existing counter, when we increment, we have to tell that counter to increment twice.
public class DoubleCounterThree
extends Counter
{
Counter counter;
public DoubleCounterThree(Counter counter)
{
this.counter = counter;
} // DoubleCounterThree(Counter)
@Override
public void increment()
{
this.counter.increment();
this.counter.increment();
}
@Override
public void reset()
{
this.counter.reset();
}
@Override
public void toString()
{
return this.counter.toString();
}
@Override
public void get()
{
return this.counter.get();
}
} // class DoubleCounterThree
This is a strange approach. Why inherit if we're going to replace EVERY SINGLE METHOD? Polymorphism: We can use one of these DoubleCounterThree thingys any place we wanted a counter.
How does the user see differences?
Counter c1 = new Counter(0);
Counter c2 = new DoubleCounterTwo(0);
Counter c3 = new DoubleCounterThree(c1);
Counter c33 = new DoubleCounterThree(c3);
c1.get(); // 0
c2.increment();
c1.get(); // 0
c2.get(); // 2
c3.increment();
c1.get(); // 2
c3.get(); // 2
c1.reset();
c33.increment();
c1.get(); // 4
c3.get(); // 4
c33.get(); // 4
Complexity: These objects have a "is a" relationship with Counters, they also have a "has a" relationship with Counters. Some designers say that having both relationships is a bad idea. But ... BufferedReader IS A Reader HAS A Reader. In practice, we try the joint IS-A/HAS-A relationships mostly with interfaces.
Another solution, that gets similar behavior
increment becomes this.val += incrementBy.DoubleCounterFour simply sets its increment to twice the increment
of its parameterSam doesn't like modifying existing classes. Sam also likes the polymorphic behavior of the DoubleCounterThree.