DEV Community

Cover image for Case Study on Object-Oriented Thinking
Paul Ngugi
Paul Ngugi

Posted on

Case Study on Object-Oriented Thinking

Case Study: Designing the Course Class

This section designs a class for modeling courses. Suppose you need to process course information. Each course has a name and has students
enrolled. You should be able to add/drop a student to/from the course. You can use a class to model the courses, as shown in Figure below.

Image description

A Course object can be created using the constructor Course(String name) by passing a course name. You can add students to the course using the addStudent(String student) method, drop a student from the course using the dropStudent(String student) method, and return all the students in the course using the getStudents() method. Suppose the Course class is available; the program below gives a test class that creates two courses and adds students to them.

Image description

The Course class is implemented in the program below. It uses an array to store the students in the course. For simplicity, assume that the maximum course enrollment is 100. The array is created using new String[100] in line 5. The addStudent method (line 12) adds a student to the array. Whenever a new student is added to the course, numberOfStudents is increased (line 14). The getStudents method returns the array. The dropStudent method (line 29) is left as an exercise.

Image description

The array size is fixed to be 100 (line 5), so you cannot have more than 100 students in the course. You can improve the class by automatically increasing the array size.

When you create a Course object, an array object is created. A Course object contains a reference to the array. For simplicity, you can say that the Course object contains the array.

The user can create a Course object and manipulate it through the public methods addStudent, dropStudent, getNumberOfStudents, and getStudents. However, the user doesn’t need to know how these methods are implemented. The Course class encapsulates the internal implementation. This example uses an array to store students, but you could use a different data structure to store students. The program that uses Course does not need to change as long as the contract of the public methods remains unchanged.

Case Study: Designing a Class for Stacks

This section designs a class for modeling stacks. Recall that a stack is a data structure that holds data in a last-in, first-out fashion, as shown in Figure below.

Image description

Stacks have many applications. For example, the compiler uses a stack to process method invocations. When a method is invoked, its parameters and local variables are pushed into a stack. When a method calls another method, the new method’s parameters and local variables are pushed into the stack. When a method finishes its work and returns to its caller, its associated space is released from the stack.

You can define a class to model stacks. For simplicity, assume the stack holds the int values. So name the stack class StackOfIntegers. The UML diagram for the class is shown in Figure below.

Image description

Suppose that the class is available. The test program below uses the class to create a stack (line 6), store ten integers 0, 1, 2, . . . , and 9 (line 9), and displays them in reverse order (line 12).

Image description

How do you implement the StackOfIntegers class? The elements in the stack are stored in an array named elements. When you create a stack, the array is also created. The no-arg constructor creates an array with the default capacity of 16. The variable size counts the number of elements in the stack, and size – 1 is the index of the element at the top of the stack, as shown in Figure below. For an empty stack, size is 0.

Image description

The StackOfIntegers class is implemented in the program below. The methods empty(), peek(), pop(), and getSize() are easy to implement. To implement push(int value), assign value to elements[size] if size < capacity (line 26). If the stack is full (i.e., size >= capacity), create a new array of twice the current capacity (line 21), copy the contents of the current array to the new array (line 22), and assign the reference of the new array to the current array in the stack (line 23). Now you can add the new value to the array (line 26).

package demo;

public class StackOfIntegers {
    private int[] elements;
    private int size;
    public static int DEFAULT_CAPACITY = 16;

    /** Construct a stack with the default capacity 16 */
    public StackOfIntegers() {
        this (DEFAULT_CAPACITY);
    }

    /** Construct a stack with the specified maximum capacity */
    public StackOfIntegers(int capacity) {
        elements = new int[capacity];
    }

    /** Push a new integer to the top of the stack */
    public void push(int value) {
        if(size >= elements.length) {
            int[] temp = new int[elements.length * 2];
            System.arraycopy(elements, 0, temp, 0, elements.length);
            elements = temp;
        }

        elements[size++] = value;
    }

    /** Return and remove the top element from the stack */
    public int pop() {
        return elements[--size];
    }

    /** Return top element from the stack */
    public int peek() {
        return elements[size - 1];
    }

    /** Test whether the stack is empty */
    public boolean empty() {
        return size == 0;
    }

    /** Return the number of elements in the stack */
    public int getSize() {
        return size;
    }
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)