CSC 207

Object-oriented Programming, Data Structures, and Algorithms

Reading

From Dr. Osera: https://osera.cs.grinnell.edu/ttap/data-structures/object-oriented-modeling.html

Lecture: Object-oriented Modeling

29 January 2025

Slides are available here: CSC207_29Jan2025

Please do not read ahead, there are Question/Answer sections. However I know that not everyone can easily see the projector, so you are free to follow along here.

Lab: Extending the Counter Class

In the recent readings, you should have learned about the Counter class. We started with the basics of a counter: It should have a value, it should initialize to 0, and it should be able to increment.

public class Counter {
    public int value;

    public Counter() {
        this.value = 0;
    }

    public void increment() {
        this.value += 1;
    }
}

The reading continued with abstraction (hiding the value from clients) and style (javadocs).

Part 1: Implement the Counter Class

In the first part of the class, I would like you to implement the Counter class with the additional changes from the reading. That is:

  • Hide the value from the client
  • Implement a getter method
  • Implement a setter method that rejects negative numbers
    • Throw a descriptive error if the client tries to set the value to a negative number
  • Follow the style guide: https://osera.cs.grinnell.edu/ttap/data-structures-labs/style-guide.html
    • This includes Javadoc comments above all public methods. At a minimum include @param and @return tags

Part 2: Extending the Counter Class

This section is based on ideas from Dr. Johnson https://johnsonba.cs.grinnell.edu/CSC207/2022S/labs/objectsandclasses.html and Dr. Rebelsky https://rebelsky.cs.grinnell.edu/Courses/CSC207/2024Sp/labs/intro-classes.html

  • Implement a method, reset, which resets the counter to 0
  • Implement a private name field (String) that is set when the counter is created
    • This should involve passing “name” to the constructor
  • Implement a method, toString, that returns “<name>: <value>”
    • Most classes should have a toString method that returns human-readable output
    • Compare the output of System.out.println() before and after the implementation of toString
  • Implement a method, clone, which clones the counter.
    • clone takes an object and traditionally makes an exact copy
    • However, given our “name” field that we wish to be unique, this clone will need to generate a new name
  • Experiment your methods to ensure they work as intended
    • I’m not asking for a detailed test suite, just a few experiments that show that your methods work, and that you’ve thought about edge cases (e.g. trying to set the value to a negative number)

Minimal example: does not try to break the methods, does not check edge cases

public static void main(String[] args) {
    Counter will = new Counter("Will");
    System.out.println(will); // Print current value: expect Will: 0
    will.increment();
    System.out.println(will); // Print current value: expect Will: 1
    System.out.println(will.getValue()); // Print current value: expect 1
    Counter pm = will.clone();
    will.setValue(5);
    System.out.println(will);// Print current value: expect Will: 5
    System.out.println(pm); // Print current value: expect ??: 1 (not spoiling how to implement clone)
    pm.reset();
    System.out.println(pm); // Print current value: expect ??: 0 (not spoiling how to implement clone)
}

Please submit your Counter Class to Gradescope

Part 3: For those with Extra Time – ExtendedCounter Class

There are many other methods that we can think of that would be useful in a counter like class. Perhaps we want to be able to add a number other than 1. Perhaps we want to be able to decrement the counter. If we allow these changes, we might want to know other values such as the maximum value the counter achieved. The following methods extend the Counter class and hopefully help you to better understand how to work with and change the state of an object.

Please follow the steps below in order, experimenting with your methods along the way, and continuing to follow the style guide.

Setting up the new class:

  • Create a new class, ExtendedCounter, and copy your methods and instance variables from the Counter class. (Do not modify your counter class for this section).
  • Remove the clone, reset, and setValue methods

Changes other than +1

  • Extend your increment method to allow for (integer) changes greater than 1
  • Extend your increment method to allow for negative and 0 changes

Maximum and minimum values

  • Implement a method to return the maximum value that the counter has reached
  • Implement a method to return the minimum value that the counter has reached

Greatest Changes

  • Implement a method to return the maximum value that the counter has been incremented by in a single step
  • Implement a method to return the minimum value that the counter has been incremented by in a single step
  • Implement a method to return the maximum absolute value change in the counter in a single step (remember that you can “increment” by negative numbers)

Reset and Clone

  • Re-implement your reset method. What else needs to reset?
  • Re-implement your clone method. What else needs to be cloned?

Additional Thoughts

  • Think back to the changes section. What do you return as the max/min increments if:
    • You only increment by positive numbers
    • You only increment by negative numbers
  • Is what you return reasonable? Is there another value that you think would be reasonable?
    • Why would you choose one of these values over the other?

Minimal example: does not try to break the methods, does not check edge cases. Does not check clone, additional parts of reset. If we instantiate a new ExtendedCounter object, then increment by 1, 1, 5, 3, -2, -6, -4, 1 we would expect to see the following:

        ExtendedCounter sky = new ExtendedCounter("Sky");
        sky.increment(1);
        sky.increment(1);
        sky.increment(5);
        sky.increment(3);
        sky.increment(-2);
        sky.increment(-6);
        sky.increment(-4);
        sky.increment(1);
        System.out.println(sky.getValue());// expect value to be -1
        System.out.println(sky.getMaxValue());// expect value to be 10
        System.out.println(sky.getMinValue());// expect value to be -2
        System.out.println(sky.getMaxInc());// expect value to be 5
        System.out.println(sky.getMinInc());// expect value to be -6
        System.out.println(sky.getMaxAbsChange());// expect value to be 6
        sky.reset();
        System.out.println(sky);// expect value to be 0