CS 161 Lab D - The Ventriloquist
Due Fri Feb 13 at the start of class
Overview
In this lab, you will be implementing a program to create a simple Ventriloquist routine. The routine will be performed in the BlueJ Terminal: that is, actions will be printed out as text.
This lab should be completed in pairs. You will need to find a different partner than you had for the last lab. Be sure to review the pair programming guidelines before you begin; remember to switch off who is driving and who is navigating!
Objectives
- To practice defining Java classes from scratch--including instance variables, constructors, getters/setters, and object methods.
- To practice calling methods you have defined.
- To practice passing Objects as parameters.
Necessary Files
You will be creating your own program from scratch for this assignment---select "Project > New Project" from the BlueJ menu to create a new project. Be sure and note where you create the project folder, so you can upload it when you're done.
Assignment Details
For this program, you will need to create three (yes, 3!) new classes: Ventriloquist
, Dummy
, and VentriloquistRoutine
. The first two of these are object classes--that is, they are classes intended to be instantiated as objects. The last is a main or tester class--that is, it has a single
static
method and runs an algorithm that instantiates and uses the other two classes.
The individual classes are detailed below; you should read through the whole assignment to get a sense for how things fit together.
Part 1: Designing the Dummy
In class we talked briefly about a "6-Step Design Plan" (described in the textbook on page 99). This is a behavior-focused design process that we'll practice here.
- Step 1: Determine the Behaviors.
-
Before you jump straight into programming, its a really good idea to read the requirements (the assignment) first! The requirements are described below:
-
Each
Dummy
will need to have a name. The dummy will also need to be able toreturn
its name and even change its name (like with a getter and a setter). -
Each
Dummy
also has an imaginary button hidden at the bottom that performs a specialAction. When called, this method prints out that the Dummy performs a particular action. For example, if aDummy
is named"Joel"
and its special action is"wiggles his ears"
, then code like:dummy.doSpecialAction(); //dummy is the name of the Dummy object
Joel wiggles his ears.- The special action String should be remembered (hint: as an instance variable!) by each Dummy object.
-
In order to instantiate (create) a
new
Dummy
object, it must be provided with a name and a special action.
-
Each
- Step 2: Write Down the Method Signatures (the "Public Interface")
-
This is a kind of outlining step--we'll create the "skeleton" for our class's methods before we start trying to fill in all the details. This will make it so we can test the class if needed!
-
We'd like to be able to write out code such as:
//instantiate a new dummy Dummy myDummy = new Dummy("David", "raises his eyebrow"); System.out.println(myDummy.getName() + " says, 'I love cats'"); myDummy.doSpecialAction(); System.out.println(myDummy.getName() + " says, 'I want to change my name to Joel'"); myDummy.setName("Joel"); myDummy.doSpecialAction();
Which should output the following to the terminal:
David says, 'I love cats' David raises his eyebrow. David says, 'I want to change my name to Joel' Joel raises his eyebrow.
- Now we can start writing some code! Make a new class
Dummy
in your BlueJ project (you'll need to make a new project if you haven't already). Remember to delete all the extra code BlueJ provides (but leave the class declaration). -
Notice the methods used in the above example? Think about what their signatures look like (e.g., what is the name of the method, the parameters of the method, and the return type (if any) of the method?) Using this analysis, and the description of the class presented in Part 1, write down the method signatures to the Dummy class.
- Leave the block (what goes inside the
{ }
) empty for now, just focus on the signature. - Hint: remember to include the signature for the constructor and any getters/setters.
- Leave the block (what goes inside the
- It's not a bad idea to check in with us once you've done this to make sure you're on the right track!
-
We'd like to be able to write out code such as:
- Step 3: Document the Public Interface
-
Now we add some comments to make sure we understand the public interface (and can explain it later!)
-
For each method in your Dummy class, add a comment that include the following components:
- Describe the method
- Describe the parameters (the inputs)
- Describe the returned value (the output)
-
An easy way to do this is to make comments in Javadoc style. These comments have the following format:
/** * Write a brief description of the method up here. * @param paramName Describe the first parameter here (if any, otherwise leave this off) * @param paramName Describe the second parameter here (if any, otherwise leave this off) * @return Describe the returned value here (if any, otherwise leave this off) */
- At this point, the formatting isn't as important as making sure you include the 3 parts to your comments.
- You can check that your JavaDoc looks correct by clicking on the "Source Code" drop-down at the top of your code and selecting "Documentation":
-
For each method in your Dummy class, add a comment that include the following components:
- Step 4: Determine the Attributes (instance variables)
-
Now that we have the outline of our behavior, lets think about what data we will need to store--what instance variables will the class need?
-
Recall that instance variables are declared with the format:
private dataType attributeName;
We always make instance variables private, and only declare them at the top of the file.
-
Remember that attributes should describe your
Dummy
object--don't make instance variables for "temporary" values!
-
Recall that instance variables are declared with the format:
- Step 5: Implement the Methods
-
Finally, we can add in the statements that tell our class how to perform each of its methods (algorithms)!
- I recommend you start with the easy methods first: the constructor will need to initialize instance variables, and setters and getters have an easy-to-follow template.
- As always, use a "write a little, compile & test; write a little more" workflow. You can test out every couple of statements you make--at the very least test out each method before you move on to the next!
- Step 6: Test the Class
-
The easiest way to test your methods is to write some code in BlueJ's Code Pad (found in the lower-right corner; select View > Show Code Pad if it isn't there). That way you can test that the methods do what you want when you call them, rather than relying on BlueJ's interface to do the work.
- You can type in the sample interaction from Step 2, and if things are working properly, you should be seeing the exact output that we gave you to the Terminal.
- If you haven't yet, this is a good time to switch drivers!
Part 2: Designing the Ventriloquist
Ventriloquist
Using the 6-Step "design algorithm" described above, you should now create the Ventriloquist
class. Note that the Ventriloquist
is a little more complex, but not by much (it just has more methods!)
- Make sure to switch drivers after every few methods you implement!
The requirements of the Ventriloquist
class are described below:
- Each
Ventriloquist
has a given name. The Ventriloquist can also return its name, but it will never need to change its name (hint: it has a getter, but no setter). -
In addition each
Ventriloquist
will need to remember aDummy
object--the puppet it is currently holding! Because we want to remember this Object, it will need to be stored as an instance variable: remember that Objects have a dataType that is the same as their class name (so apuppet
variable may have a dataType ofDummy
). -
The
Ventriloquist
is able to pick up a dummy using a method calledpickUpDummy()
. This method will work very similarly to a setter (and should have a return type and parameter as such). However, in addition to setting the puppet, this method should print out that the ventriloquist picked up the dummy. This will be useful for testing (and for your routine later on!) -
Your
Ventriloquist
class will need to have a constructor. Your constructor should take in the name of the ventriloquist.-
Watch Out: Because Ventriloquists aren't created with a Dummy, it is possible that the nametag for the Ventriloquist's Dummy instance variable won't be attached to anything. In computer science, we say that an empty variable contains a special value called
null
.If you try and call a method on the value inside an empty variable (so you try and tell the Dummy to do something, when there is no Dummy with the nametag), you will get what is called a
NullPointerException
--you've pointed atnull
and told it to do something, andnull
can't do anything (because it is nothing!). If you get this error, make sure that you've put a value in the variable before you call a method on that variable!This is a new concept and can be confusing. Please let me know if you have any problems or need help with this!
-
-
Your
Ventriloquist
should also have atoString()
method so you can print out the object. The method should return a value such as"Emily and the amazing Joel"
(where Emily is the Ventriloquist and Joel is the Dummy).Remember, a
toString()
method does not actually print anything, it just returns a String that can be printed elsewhere (like from the VentriloquistRoutine)! -
Your
Ventriloquist
should have asay
method that has the ventriloquist speak. This method should take in the line that the ventriloquist will say, and then print out that it says that line. For example:Ventriloquist emily = new Ventriloquist("Emily"); emily.say("Hello World");
Will output:
Emily says 'Hello World'- Remember to include the single quotation marks when you print! These are important for the show to look good
-
Your
Ventriloquist
can also make the puppet speak a given line. This method should be calledventriloquize()
. This method should print out that the dummy says the given line. For example, if the ventriloquist Emily has the Dummy Joel:emily.ventriloquize("I'm such a dummy!");
Will output:
Joel says 'I'm such a dummy!'- This method will need to ask the Dummy for its name, and then use that to determine what to print. Remember to add in the single quotes to whatever line is being spoken!
-
Your
Ventriloquist
has a way to make its Dummy use its special action (that is, the ventriloquist hits the secret button). This method should be calleduseSpecialAction()
.- This method should just call the appropriate method on the dummy!
-
Your
Ventriloquist
should have 3 additional methods that will allow it to do the classic trick of having the puppet talk while the ventriloquist is drinking a glass of water.It should have a
startDrinking()
method that prints out that the ventriloquist has started drinking:Emily starts chugging a glass of water
and a
stopDrinking()
method that prints out that the ventriloquist has stopped drinking:Emily stops chugging a glass of water
Finally, the
Ventriloquist
should have adrinkAndSpeak()
method that takes in a line to say. This method should have the ventriloquist start drinking, ventriloquize the line, and then stop drinking.-
This method should call the previous methods you wrote!
Remember you can call a method on the current object by using
this.myMethod(parameters);
-
This method should call the previous methods you wrote!
Remember you can call a method on the current object by using
-
Here is an example set of code that uses the Ventriloquist and the Dummy classes:
//instantiate a new Ventriloquist named Emily Ventriloquist emily = new Ventriloquist("Emily"); //instantiate two dummies Dummy dummy1 = new Dummy("David", "raises his eyebrow"); Dummy dummy2 = new Dummy("Joel", "bites his nails"); //do a routine emily.pickUpDummy(dummy1); //pick up a Dummy (David) System.out.println("Introducing " + emily); emily.say("Hello, " + dummy1.getName() + "!"); emily.ventriloquize("Hello yourself!"); emily.useSpecialAction(); emily.pickUpDummy(dummy2); //pick up a different Dummy (Joel) emily.say("Hi, " + dummy2.getName() + "!"); emily.ventriloquize("I don't like my name."); emily.say("Well then let's change it to Hans"); emily.useSpecialAction(); dummy2.setName("Hans"); emily.ventriloquize("You may call me " + dummy2.getName()); emily.say("Hello, " + dummy2.getName() + "!"); emily.ventriloquize("Much better."); emily.drinkAndSpeak("And her lips aren't even moving!");
This should print the following to the terminal:
Emily picks up David Introducing Emily and the Amazing David! Emily says 'Hello, David!' David says, 'Hello yourself!' David raises his eyebrow Emily picks up Joel Emily says 'Hi, Joel!' Joel says, 'I don't like my name.' Emily says 'Well then let's change it to Hans' Joel bites his nails Hans says, 'You may call me Hans' Emily says 'Hello, Hans!' Hans says, 'Much better.' Emily starts chugging a glass of water. Hans says, 'And her lips aren't even moving!' Emily stops chugging a glass of water.
Part 3: Creating Your Own Routine
- You'll quickly find that it's a bit tedious to type all that routine into the Code Pad. So you should create a new class that will perform the routine for you automatically. Call this class
VentriloquistRoutine
. -
This class should have exactly one method:
public void start()
-
Inside this method, you should instantiate a
Ventriloquist
object ("Emily" in the above example), as well as at least twoDummy
objects ("Joel" and "David" in the above example). Your ventriloquist should perform a routine similar to the one described above using these objects.- Make sure that the routine lets the Ventriloquist show off all its tricks: using the Dummys' special actions, doing the drinkAndSpeak trick, etc.
- You might start by copy-and-pasting the above routine, then modifying it as desired. You must create your own routine though!
- Remember: The Dummy doesn't actually ever do anything--the Ventriloquist does all the work (it just looks like the dummy is doing it). In fact, you should almost never need to call a method on the Dummy objects (except possible to ask them for and change their names).
Submission
-
Make sure both of your names are on all of the classes you've created (
Ventriloquist
,Dummy
, andVentriloquistRoutine
). If your names aren't on your assignment, we can't give you credit! -
Right-click on the project folder you downloaded, then:
- If using Linux, select Compress...
- If using Windows, select Send to and then Zip file
- If using Mac, select Compress ... items
This will let you take the selected folder (or files) and generate a new compressed
.zip
file. -
Navigate to the course on Moodle
(Lecture Section A),
(Lecture Section B).
Upload your
.zip
file to theLab D Submission
page. Remember to click "Save Changes"! You may submit as often as you'd like before the deadline; we will grade the most recent copy. - While you're on Moodle, remember to fill out the Lab D Partner Evaluation. Both partners need to submit evaluations.
Grading
This assignment will be graded out of 28 points.
- Dummy (8pt)
- [2pt] Your Dummy class's methods all have appropriate parameters and return values
- [2pt] Your Dummy class's methods all have comments describing the function, parameters, and return type.
- [1pt] Your Dummy class has appropriate instance variables
- [1pt] Your Dummy class has appropriate constructors
- [1pt] Your Dummy class has appropriate getter/setters
- [1pt] Your Dummy can perform its special action
- Ventriloquist (14pt)
- [2pt] Your Ventriloquist class's methods all have appropriate parameters and return values
- [1pt] Your Ventriloquist class's methods have comments
- [1pt] Your Ventriloquist class has appropriate instance variables
- [1pt] Your Ventriloquist class has appropriate constructors
- [1pt] Your Ventriloquist class has appropriate getters/setters
- [1pt] Your Ventriloquist can pick up a Dummy
- [1pt] Your Ventriloquist class has a proper
toString()
method - [1pt] Your Ventriloquist can speak a given phrase
- [1pt] Your Ventriloquist can ventriloquize a given line
- [1pt] Your Ventriloquist can activate the dummy's special action
- [1pt] Your Ventriloquist can perform the "drink-and-speak" trick
- [2pt] Your "drink-and-speak" trick re-uses previous methods
- VentriloquistRoutine (4pt)
- [1pt] You have created the VentriloquistRoutine with a single start() method
- [1pt] Your start() method runs a complete ventriloquist routine!
- [1pt] Your routine uses at least 2 dummies.
- [1pt] Your routine shows off all of the ventriloquist's functionality
- Style & Documentation (2pt)
- [1pt] Your code is properly formatted (indentation, etc) and methods/variables are properly named
- [1pt] Submitted a lab partner evaluation