CSA FRQ #4

Directions:

SHOW ALL YOUR WORK. REMEMBER THAT PROGRAM SEGMENTS ARE TO BE WRITTEN IN JAVA.

Notes:

  • Assume that the classes listed in the Java Quick Reference have been imported where appropriate.
  • Unless otherwise noted in the question, assume that parameters in method calls are not null and that methods are called only when their preconditions are satisfied.
  • In writing solutions for each question, you may use any of the accessible methods that are listed in classes defined in that question. Writing significant amounts of code that can be replaced by a call to one of these methods will not receive full credit.

This question involves the design of an interface, writing a class that implements the interface, and writing a method that uses the interface.

(a) A number group represents a group of integers defined in some way. It could be empty, or it could contain one or more integers.

Write an interface named NumberGroup that represents a group of integers. The interface should have a single contains method that determines if a given integer is in the group. For example, if group1 is of type NumberGroup, and it contains only the two numbers -5 and 3, then group1.contains(-5) would return true, and group1.contains(2) would return false. Write the complete NumberGroup interface. It must have exactly one method.

public interface NumberGroup {
    boolean contains(int number);
}

(b) A range represents a number group that contains all (and only) the integers between a minimum value and a maximum value, inclusive. Write the Range class, which is a NumberGroup. The Range class represents the group of int values that range from a given minimum value up through a given maximum value, inclusive. For example,the declaration

NumberGroup range1 = new Range(-3, 2);

represents the group of integer values -3, -2, -1, 0, 1, 2.

Write the complete Range class. Include all necessary instance variables and methods as well as a constructor that takes two int parameters. The first parameter represents the minimum value, and the second parameter represents the maximum value of the range. You may assume that the minimum is less than or equal to the maximum.

public interface NumberGroup {
    boolean contains(int number);
}

public class Range implements NumberGroup {
    private int min;
    private int max; //instance variables

    public Range(int min, int max) { //constructor
        this.min = min;
        this.max = max;
    }

    @Override
    public boolean contains(int number) {
        return number >= min && number <= max; //testing if value is in the range
    }
}

NumberGroup Rangetest = new Range(-3, 2);
System.out.println("test.contains(1): " + Rangetest.contains(1));
System.out.println("test.contains(10): " + Rangetest.contains(10));

test.contains(1): true
test.contains(10): false

(c) The MultipleGroups class (not shown) represents a collection of NumberGroup objects and isa NumberGroup. The MultipleGroups class stores the number groups in the instance variable groupList (shown below), which is initialized in the constructor.

private List groupList;

Write the MultipleGroups method contains. The method takes an integer and returns true if and only if the integer is contained in one or more of the number groups in groupList.

For example, suppose multiple1 has been declared as an instance of MultipleGroups and consists of the three ranges created by the calls new Range(5, 8), new Range(10, 12), and new Range(1, 6). The following table shows the results of several calls to contains.

image

public interface NumberGroup {
    boolean contains(int number);
}

public class MultipleGroups implements NumberGroup {
    private List<NumberGroup> groupList;

    public MultipleGroups(List<NumberGroup> groupList) {
        this.groupList = groupList;
    }

    public boolean contains(int number) {
        for (NumberGroup group : groupList) {
            if (group.contains(number)) {
                return true;
            }
        }
        return false;
    }

}

MultipleGroups multiple1 = new MultipleGroups(List.of(new Range(5, 8), new Range(10, 12), new Range(1, 6)));
boolean result1 = multiple1.contains(2);
boolean result2 = multiple1.contains(6);
boolean result3 = multiple1.contains(9); // Example call to contains
System.out.println("Contains 2? " + result1 + ", Contains 6? " + result2 + ", Contains 9? " + result3);
Contains 2? true, Contains 6? true, Contains 9? false

Explanation and Reflection:

As I’ve not experineced interface enough compared to the rest of the topics, understanding the basics of interface took time and had to look up how it works. Once I understood the basics, this problem was actually not that challenging at all compared to the rest of the questions.

I’ve learned that an interface is a collection of abstract methods. It defines a contract that classes must adhere to. Unlike abstract classes, an interface can only have abstract methods (methods without a body) and constants (final variables). Any class that implements an interface must provide implementations for all the methods declared in the interface.

When understanding interfaces, I thought that the structure kind of looks like the same as inheritance. This is probably because they both provide a way to achieve abstraction and share common behavior among classes.

Here is an example below as demonstration:

Interface:

// Example interface
interface SoundMaker {
    void makeSound();
}

// Class implementing the interface
class Cat implements SoundMaker {
    @Override
    public void makeSound() {
        System.out.println("Meow! Meow!");
    }
}

The Dog class extends the Animal class, inheriting the makeSound method. Now, when an instance of Dog is created, it can use the makeSound method from the Animal class.

Inheritance:

// Base class using inheritance
class Animal {
    void makeSound() {
        System.out.println("Some generic sound");
    }
}

// Derived class inheriting from Animal
class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Woof! Woof!");
    }
}

In this example, the Dog class extends the Animal class, inheriting the makeSound method. Now, when an instance of Dog is created, it can use the makeSound method from the Animal class.

Inheritance, demonstrated by the Dog class inheriting from the Animal class, allows the inherited class to reuse and extend the behavior of the base class. Similarly, interfaces, as seen in the Cat class implementing the SoundMaker interface, allow for classes that need to provide specific functionality. This promotes code consistency as classes implementing the interface are required to adhere to the specified methods.

In the problem, we can see that this line:

boolean contains(int number);

is called in this if statement:

if (group.contains(number)) {
               return true;
           }

to declare whether or not the number provided is in the array or not. If it isn’t it will respond with a boolean value (true or false).