OVERVIEW In today’s lab, we will create abstracts classes, and multiple classes (and objects) that implement the same interface.
For this exercise, we will continue working with the CounterWithMemory
you created in Lab 11: Inheritance. Another potentially useful method returns a String
representation of the current tally. We can imagine that, for some applications (such as logging the counts over a long period of time), we might want the String
representation to include with the tally count the name of the counter and a time stamp that records current date and time, while in other cases we just want just the base-ten numeral corresponding to the current tally.
One way to arrange this is to add an abstract method to the CounterWithMemory
class and then to derive two (or possibly more) classes from it, containing different implementations of the abstract method.
Add abstract method show
to the definition of the CounterWithMemory
class. This method takes no arguments and returns a String
. To do this, you must change the CounterWithMemory
class to be an abstract class.
Define two new derived classes: BasicCounterWithMemory
and LoggingCounterWithMemory
. One key difference between them will be how they implement the show
method. The BasicCounterWithMemory
class show
method returns just the base-ten numeral for the current tally.
The LoggingCounterWithMemory
should create a show method that returns a String
that also contains the counter’s name and a time stamp. (You can get the current date and time by importing the java.util.Date class
and calling its zero-argument constructor. Objects of this class have a toString
method that return time stamps accurate to the second.)
Note that BasicCounterWithMemory
and LoggingCounterWithMemory
classes need to have a one-argument constructor. What is the argument of these constructors?
This interface — call it Responder
— consists of a single abstract method, respond
, which takes one argument, a String, and returns a String. The idea is that a Responder can, in effect, hold up one end of a conversation, speaking whenever it is spoken to; the String that the respond method returns is the object’s reply to the String that that method receives as argument.
In Eclipse, start a new project called conversation
, and in that project create the Responder
interface.
Write an opening comment to introduce the Responder
interface, then write the Java code to define that interface.
An Echo
is an object that implements the Responder
interface with a respond
method that always returns the same String
that it receives.
Document and write a definition for the Echo
class.
Start a JUnit test class ResponderTester
, to test the various kinds of Responders
that you will define in this lab.
Write tests for the Echo
class and then compile and run ResponderTester
and confirm that your implementation of the Echo
class passes the test.
A Bore
is an object that implements the Responder
interface with a respond
method that ignores the String
it receives and always replies with the same fixed String
. The Bore
class has a one-argument constructor through which the programmer specifies its constant response.
Bore
class.A Disemvoweler
is an object that implements the Responder
interface with a respond
method that removes all the vowels from the String
it receives and returns the result. (Comment moderators in social networks sometimes apply the disemvoweling operation to comments contributed by trolls, so to express a degree of disapprobation without complete censorship.)
Disemvoweler
class. To implement the respond method, you may use replaceAll
method of String class. This method takes two String parameters. It replaces all occurances of the first parameter with the second parameter. (Read the documentation)A Recapitulator
is an object that implements the Responder
interface with a respond method that replies with the null String
the first time it is invoked, and replies to any subsequent invocation with the concatenation of all the strings that it has previously received as arguments, each terminated with a newline character.
Suppose obj is an object reference for Recapitulator
. Here are the expected outputs after each call to respond method:
System.out.println(obj.respond("hello")); // null
System.out.println(obj.respond("world")); // hello
System.out.println(obj.respond("!")); /* hello
world */
Recapitulator
class.A Numberer
is an object that implements the Responder
interface by tweaking the operation of another Responder
object, numerand
. When a Numberer
receives the respond
message, it takes the argument and sends numerand
a respond
message with the same argument. Numberer
then receives numerand’s reply, prepends a serial number to it (“1:” on the first invocation, “2:” on the second, and so on), and returns the result.
Use the String.format
method to create the reply/response from Numberer
.
Here’s an example of the kind of exchange that takes place when numerand is a Disemvoweler
:
- if you call numberer.respond( "Hello!" ) the result is `1:Hll!`
- then if you call numberer.respond("Is anyone there?") the result is `2:s nyn thr?`
Numberer
class. In this case, “test” means to write a program that calls the methods in your Numberer class. Note that the constructor needs another Responder
as its argument. Use the format method from the String
class to display the reply from Numberer
.A Composer
is an object that implements the Responder
interface by combining the operations of two other Responder
objects—let’s call them fore
and aft
. When a Composer
receives the respond
message, it takes the argument and sends fore
a respond
message with that argument. When fore
replies, the Composer
sends aft
a respond
message with that reply as its argument. The Composer
returns aft
’s reply as its own response to the respond message it received.
If, for instance, fore
is a Bore
that replies to any conversational opening with the response “Hi, I’m having fun learning Java!”, and aft
is a Disemvoweler
, then the Composer
would respond to the string “Hello – pleased to meet you.” with the string “H, ‘m hvng fn lrnng Jv!”.
The Composer
class needs a two-argument constructor through which the programmer can specify fore
and aft
.
Document, write, and test a definition for the Composer
class.
You will submit your files via Gradescope by the end of the week.
CounterWithMemory
, BasicCounterWithMemory
and LoggingCounterWithMemory
classes, the JUnit Test case, the UML diagram, and a screenshoot of the JUnit test output (JUnit view).I strongly recommend that each student keep a copy of the lab. Therefore, don’t forget to share the files/folder with your lab partner!
Remember: Write your code anticipating errors and print user-friendly error messages, all your public methods should be well documented (use Javadoc comments). You should include comments or organize your code and lab report in a way that will help the grader to find the answer to the exercises or posted questions.