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.

  1. 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.

  2. Inside the folder, issue the command dotnet new console to create the project in the folder.

  3. Still inside the project directory, type code . to start VS Code with the folder as the default folder.

  4. Prepare your code in VS Code using the file Program.cs to code unless otherwise specified.

  5. The namespace of this project is IntroCSCS but you may use something else such as IntroCS as long as it is consistent among classes.

  6. The class name of this project is Ch10ClassesLab if program.cs is used.

  7. When executing code, you will mostly start with the Main() method in a designated class/file.

  8. You will prepare methods in the same class or project mainly to be called from the Main() method.

  9. Use a Word document to prepare your assignment.

  10. Number the questions and annotate your answers (using // in code) to show your understanding.

  11. 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.

  1. 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 a gut. In our version the gut is a List of strings describing the contents, in the order eaten. A newly created Animal gets a name from a parameter passed to the constructor, while the gut 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 the gut. If Froggy eats “worm” and then “fly”, its gut list contains “worm” and “fly”.

    • An Animal can Excrete (printing abd removing what was first in the gut List). Recall the method RemoveAt in List. Print the empty string, “”, if the gut was already empty. Following the Froggy example above, Froggy could Excrete, and “worm” would be printed. Then its gut would contain only “fly”.

    • A ToString method (ToString Override): Pay attention to the override 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.

  2. Complete the file test_animal.cs with its class TestAnimal containing the Main 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.