10.5. Lab: Classes
Notes on Assignments:
Notes on GAI: Note that the course policy is that you should not use generative AI (GAI) without authorization. GAI’s are great tools and you should learn how to use it, but they are tools and should be used to facilitate but not replace your learning. If you are suspected to have used GAI tools to generate answers to the assignment questions instead of using it as a learning tool, you may be called up to explain/reproduce your work. If you fail to demonstrate your competence, all your related assignments throughout the semester will be regraded as 0. For example, if you fail to produce good code in
while
loops in midterm exam, your lab06 while loop homework and lab will be re-evaluated.
Create a dotnet console app project (see Create a C# Project if you need to) in your
introcscs
directory (C:\Users\*USERNAME*\workspace\introcscs
for Windows or[COMPUTER]:introcscs [USERNAME]$
for macOS) ; call it Ch10ClassesLab.Inside the folder, issue the command
dotnet new console
to create the project in the folder.Still inside the project directory, type
code .
to start VS Code with the folder as the default folder.Prepare your code in VS Code using the file
Program.cs
to code unless otherwise specified.The namespace of this project is IntroCSCS but you may use something else such as IntroCS as long as it is consistent among classes.
The class name of this project is Ch10ClassesLab if program.cs is used.
When executing code, you will mostly start with the Main() method in a designated class/file.
You will prepare methods in the same class or project mainly to be called from the Main() method.
Use a Word document to prepare your assignment.
Number the questions and annotate your answers (using // in code) to show your understanding.
For coding questions, screenshot and paste 1) your code in VS Code and 2) the results of the code’s execution (command prompt and username are part of the execution).
10.5.1. Converting A Static Game To A Game Instance
Study this lab to get yourself familiarized with object-oriented programming.
Remember that you can only have one Main method in the project.
For a comparison of procedural
and object-oriented
coding,
consider converting Number Guessing Game so that a GuessGame
is an object, an instance of the GuessGame class.
Here is a procedural game version, example file static_version/static_version.cs
public class Game
{
private static Random r = new Random();
public static void Main()
{
int big = UI.PromptInt("Enter a secret number bound: ");
Play(big);
}
public static void Play(int big)
{
int secret = r.Next(big);
int guesses = 1;
Console.WriteLine("Guess a number less than {0}.", big);
int guess = UI.PromptInt("Next guess: ");
while (secret != guess) {
if (guess < secret) {
Console.WriteLine("Too small!");
} else {
Console.WriteLine("Too big!");
}
guess = UI.PromptInt("Next guess: ");
guesses++;
}
Console.WriteLine("You won on guess {0}!", guesses);
}
}
The project also refers to the library class UI
, with the functions we use to save
keyboard input. It is all static methods. copy ui.cs to your project folder.
Is there any reason to make this UI class have its own own instances?
No. There is no state to remember between UI method calls. What comes in through the keyboard goes out through a return value, and then you are completely done with it. A simple static function works fine each time. Do not get fancy for nothing.
What state would a game hold? We might set it up so the user
chooses the size of the range of choices just once, and remember it
for possibly multiple plays of the GuessGame. The variable was
big
before, we can keep the name.
If we are going to remember it inside our GuessGame instance,
then big
needs to become an instance variable, and it will be something
we can set in a constructor.
What actions/methods will this object have? Only one - playing a GuessGame. The GuessGame could be played multiple times, and that action, play, makes sense as a method, Play, which will look a lot like the current static function.
In the procedural
version there are several other important variables:
Random rand
: That was static before, for good reason: We only need one Random number generator for the whole time the program is running, so one static variable makes sense.The central number in the procedural Game and our future Play method is
secret
. Should that be an instance variable? It would work, but it would be unhelpful and misleading: Secret is reset every time the game is played, and it has no meaning after a Play function would be finished. There is nothing to remember between time you Play. This is the perfect place for a local variable as we have now.
A common newbie error is to make things into instance variables, just because you can, when an old-fashioned local variable is all that you need. It is good to have variables leave the programmer’s consciousness when they are no longer needed, as a local variable does. An instance variable lingers on, leaving extra places to make errors.
This introductory discussion could get you going, making a transformation.
Go ahead and make the changes as far as you can:
create project GuessGame inside the current solution.
Have a class GuessGame for the GuessGame instance,
with instance variable big
and method Play
.
You still need a static Main
method to first create the GuessGame object.
You could prompt the user for the value for big
to send to the constructor.
Once you have an object, you can call instance method Play
.
What about parameters? What needs to change from the procedural version?
A possible final result is in instance_version/guess_game.cs.
10.5.2. Animal Class Lab
Objectives:
Complete a simple (silly) class, with constructor and methods,
including a ToString
method, and a separate testing class.
Make use of your project folder, copy in the .cs files from the example project animal_lab_stub. Then modify the two files as discussed below.
Complete the simple class Animal in your copy of the file animal.cs. The bullets below name and describe the instance variables, constructor, and methods you need to write:
An Animal has a
name
and agut
. In our version thegut
is a List of strings describing the contents, in the order eaten. A newly created Animal gets aname
from a parameter passed to the constructor, while thegut
always starts off empty.An Animal has a
Greet
method, so an animal named “Froggy” would say (that is, print)Hello, my name is Froggy.
An Animal can
Eat
a string naming the food, adding the food to thegut
. If Froggy eats “worm” and then “fly”, itsgut
list contains “worm” and “fly”.An Animal can
Excrete
(printing abd removing what was first in the gut List). Recall the methodRemoveAt
in List. Print the empty string, “”, if thegut
was already empty. Following the Froggy example above, Froggy couldExcrete
, and “worm” would be printed. Then itsgut
would contain only “fly”.A
ToString
method (ToString Override): Pay attention to theoverride
keyword. Make it return a string in the format shown below for Froggy, including the Animal’s name:Animal: Froggy
Note that all the methods that print should be void.
Complete the file test_animal.cs with its class
TestAnimal
containing theMain
method, testing the class Animal: Create a couple of Animals and visibly test all the methods, with enough explanation that someone running the test program, but not looking at the code of either file, can see that everything works.