Quantcast
Channel: Object-oriented calculator - Code Review Stack Exchange
Viewing all articles
Browse latest Browse all 2

Object-oriented calculator

$
0
0

I have solved an assignment (Exercise 3) from the MOOC Object-Oriented programming with Java, part II, but I'm not enrolled in said course.

Assignment Summary:

Make a simple calculator. You may create a Reader class that encapsulates the Scanner-object in order to communicate with the user. The Scanner-object can be an instance variable. Implement class Reader with the following methods:

  • public String readString()
  • public int readInteger()

To take care of the application logic of your program, a methodpublic void start() may be used. The calculator has the commands sum, difference, product andend. Add an instance variable of the type Reader for the calculator and create the reader in the constructor. You may also implement a method private void statistics(). The method is meant to print the amount of operations done with the Calculator-object. If an invalid command is given (something other than sum, difference, product or end), the calculator should not react to the command in any way, but should instead continue by asking the next command. Statistics should not count as an invalid command as a completed calculation.

Changes made from assignment

  • The Reader class doesn't exactly encapsulate the Scanner-object, and I have only provided static methods to the class. I had wanted it to inherit from the Scanner class, but Scanner was a final class.
  • Scanner-object wasn't made an instance variable.
  • enum is used for the various calculator commands.
  • The calculator gives a message when an invalid command is given.
  • The calculator contains only static methods.
  • I have omitted method: public void start()
  • A static variable : public static boolean isRunning(), is used a state variable

How do you refactor this code so that it follows OOP, reads better, is manageable? How can I write method names and classes better? How do you know which entities are to be made separate classes, and how to use classes efficiently?

I had thought of using a separate Command class that has a list of commands to use (whether in calculator or in any other class that uses a command style execution, like a terminal), but I didn't know how to proceed with that. Functions aren't objects in Java and generalizing seems difficult even with using Reflection in Java, especially the number and type of the return values, and typecasting new parameters with said types.

Reader Class used to simplify Scanner class (It can't be inherited, it seems)

import java.util.Scanner;public class Reader {    public static String readString(String prompt) {        System.out.print(prompt);        return new Scanner(System.in).nextLine();    }    public static int readInteger(String prompt) {        return Integer.parseInt(readString(prompt));    }}

Calculator class

import java.util.stream.IntStream;public class Calculator {    private static int statistics = 0;    private static boolean isRunning = true;    enum Command {        SUM,        DIFFERENCE,        PRODUCT,        END    }    public static boolean isRunning() {        return isRunning;    }    public static Command getCommand() throws IllegalCommand {        String command = Reader.readString("command: ");        try {            return Command.valueOf(command.toUpperCase());        }        catch (Exception e) {            throw new IllegalCommand("Command "+ command +" not found");        }    }    private static void printResult(String operation, int result) {        System.out.println(operation +" of the values "+ result);    }    private static int[] readOperands(int noOfOperands) {        int[] array = new int[noOfOperands];        for (int i = 0; i < noOfOperands; i++) {            array[i] = Reader.readInteger(String.format("value%d: ", i + 1));        }        return array;    }    public static int sum(int... a) {        return IntStream.of(a).sum();    }    public static int product(int... a) {        int result = 1;        for (int i = 0; i < a.length; i++) {            result *= a[i];        }        return result;    }    public static void execute(Command command) {        switch (command) {            case SUM: {                int[] operands = readOperands(2);                printResult("Sum", sum(operands));                statistics++;                break;            }            case DIFFERENCE: {                int[] operands = readOperands(2);                printResult("Difference", operands[0] - operands[1]);                statistics++;                break;            }            case PRODUCT: {                int[] operands = readOperands(2);                printResult("Product", product(operands));                statistics++;                break;            }            case END: {                System.out.println("Calculations done "+ statistics);                isRunning = false;                break;            }        }    }}

Main

public class Main {    public static void main(String[] args) {        while (Calculator.isRunning()) {            try {                Calculator.execute(Calculator.getCommand());                System.out.println();            }            catch(IllegalCommand e) {                System.out.println(e);            }        }    }}

IllegalCommand , a custom Exception class. Is this an overkill? I just wanted to give it a type, in case it clashes with other Exception types in the future.

public class IllegalCommand extends Exception {    public IllegalCommand(String s) {        super(s);    }}

Expected output

command: sumvalue1: 4value2: 6Sum of the values 10command: productluku1: 3luku2: 2Product of the values 6command: integralIllegalCommand: Command integral not foundcommand: differencevalue1: 3value2: 2Difference of the values 1command: endCalculations done 3

Viewing all articles
Browse latest Browse all 2

Latest Images

Trending Articles





Latest Images