Methods in subclass aren't working - java

I have an assignment that was to make a subclass which adds on to the existing super class, and this is run by a third class with a main method which creates an object of the subclass and calls appropriate methods.
My problem is that calling methods in the super class works correctly, but calling the two additional methods I have written in the subclass gets ignored.
I've checked, and the main method IS getting to the if statement which calls the new method in the subclass, but this method is not executing.
Specifically the superclass is a memory calculator with basic add, subtract, divide, and multiply options, as well as an option to clear the current value.
The subclass is a scientific memory calculator that overrides the menu method in the superclass to include options for power and logarithm, and has methods for both.
When I choose the option for power, it is simply returning the current value and not raising that power to the number specified.
Superclass:
import java.util.Scanner;
public class MemoryCalc {
private double currentValue = 0;
public static int displayMenu() {
Scanner input = new Scanner(System.in);
System.out.print("Menu\n1. Add\n2. Subtract\n3. Multiply\n4. Divide\n5. Clear\n6. Quit\nWhat would you like to do? ");
int menuChoice = input.nextInt();
while (menuChoice < 1 || menuChoice > 6) {
System.out.print("Please enter a valid option.\n\n");
System.out.print("Menu\n1. Add\n2. Subtract\n3. Multiply\n4. Divide\n5. Clear\n6. Quit\nWhat would you like to do? ");
menuChoice = input.nextInt();
}
return menuChoice;
}
public static double getOperand(String prompt) {
Scanner input = new Scanner(System.in);
System.out.print(prompt);
double operand = input.nextDouble();
return operand;
}
public double getCurrentValue() {
return currentValue;
}
public void add(double operand2) {
currentValue = currentValue + operand2;
}
public void subtract(double operand2) {
currentValue = currentValue - operand2;
}
public void multiply(double operand2) {
currentValue = currentValue * operand2;
}
public void divide(double operand2) {
if (operand2 == 0) {
currentValue = Double.NaN;
}
else currentValue = currentValue / operand2;
}
public void clear() {
currentValue = 0;
}
}
Subclass:
import java.util.Scanner;
public final class ScientificMemCalc extends MemoryCalc {
private double currentValue = 0;
public static int displayMenu() {
Scanner input = new Scanner(System.in);
int menuChoice = -1;
while (menuChoice < 1 || menuChoice > 8) {
System.out.println();
System.out.println("Menu");
System.out.println("1. Add");
System.out.println("2. Subtract");
System.out.println("3. Multiply");
System.out.println("4. Divide");
System.out.println("5. Power");
System.out.println("6. Logarithm");
System.out.println("7. Clear");
System.out.println("8. Quit");
System.out.println();
System.out.print("What would you like to do? ");
menuChoice = input.nextInt();
if (menuChoice < 1 || menuChoice > 8) {
System.out.println(menuChoice + " wasn't one of the options");
}
}
return menuChoice;
}
public void power(double operand2) {
currentValue = Math.pow(currentValue, operand2);
}
public void logarithm() {
currentValue = Math.log(currentValue);
}
}
Main Method:
public class ScientificCalcDriver {
public static void main(String[] args) {
ScientificMemCalc calculator1 = new ScientificMemCalc();
int menuChoice = 0;
while (menuChoice != 8) {
System.out.print("The current value is " + calculator1.getCurrentValue() + "\n");
menuChoice = ScientificMemCalc.displayMenu();
if (menuChoice < 6) {
double Operand2 = ScientificMemCalc.getOperand("What is the second number? ");
if (menuChoice == 1) {
calculator1.add(Operand2);
}
if (menuChoice == 2) {
calculator1.subtract(Operand2);
}
if (menuChoice == 3) {
calculator1.multiply(Operand2);
}
if (menuChoice == 4) {
calculator1.divide(Operand2);
}
if (menuChoice == 5) {
calculator1.power(Operand2);
}
}
else if (menuChoice == 6) {
calculator1.logarithm();
}
else if (menuChoice == 7) {
calculator1.clear();
}
else if (menuChoice == 8) {
System.out.print("Goodbye!");
System.exit(0);
}
}
}
}

You've got two different currentValue variables, both private, one in the superclass and one in the subclass. The methods in your superclass are changing the value of its variable, and the methods of the subclass are changing the value of its variable.
Make currentValue protected in the superclass, and remove it from the subclass.
Update:
Based on the "must be private" comment: You still need to remove the extra currentValue variable in the subclass, but as Oleg points out, you can obtain and update the value of a private variable in a superclass using get and set methods defined in the superclass.

Related

How to give 2 different data types from a method

I want to do a simple beginner project using methods, if statements, and user input. I am having an issue though with the calc() method. How can I return two different data types in java, and if I cannot, how could I do it, still by using more than the main method?
import java.util.Scanner; //allow user input
public class fourFunctionCalculator{
public static void main(String[] args) {
Scanner keyboardInput = new Scanner(System.in);
System.out.print("Enter your first number:"); //get first number
double num1 = keyboardInput.nextDouble();
System.out.print("Enter your operator: "); // get operator
String name = keyboardInput.next(); //grabs everything user types until a space
System.out.print("Enter your second number: "); //get second number
double num2 = keyboardInput.nextDouble();
System.out.println(calc(num1,op,num2));
}
//troublesome part is here
public static double calc(double num1, String op, double num2){
if (op == "+") {
return (num1 + num2);
}
else if (op == "-") {
return (num1 - num2);
}
else if (op == "*") {
return (num1 * num2);
}
else if (op == "/") {
return (num1 / num2);
}
else {
return ("INVALID OPERATOR");
}
}
}
you could generate a custom Exception, also you need to use the method .equals() inside the if validations, otherwise it is not going to work.
fourFunctionCalculator.java
import java.util.Scanner; //allow user input
public class fourFunctionCalculator{
public static void main(String[] args) {
Scanner keyboardInput = new Scanner(System.in);
System.out.print("Enter your first number:"); //get first number
double num1 = keyboardInput.nextDouble();
System.out.print("Enter your operator: "); // get operator
String name = keyboardInput.next(); //grabs everything user types until a space
System.out.print("Enter your second number: "); //get second number
double num2 = keyboardInput.nextDouble();
try {
System.out.println(calc(num1,name,num2));
} catch (InvalidOperatorException e) {
System.out.println(e);
}
}
public static double calc(double num1, String op, double num2){
if (op.equals("+")) {
return (num1 + num2);
}
else if (op.equals("-")) {
return (num1 - num2);
}
else if (op.equals("*")) {
return (num1 * num2);
}
else if (op.equals("/")) {enter code here
return (num1 / num2);
}
throw new InvalidOperatorException("INVALID OPERATOR : " + op);
}
}
InvalidOperatorException.java
public class InvalidOperatorException
extends RuntimeException {
private static final long serialVersionUID = 1L;
public InvalidOperatorException(String errorMessage) {
super(errorMessage);
}
}
I recommend returning an OptionalDouble object as placeholder of something valid or not...
Ex #1: return OptionalDouble.of(num1 + num2); // first if outcome
Ex #2: return OptionalDouble.empty(); // for the last else
Then your main(...) method needs to be something like...
System.out.println(calc(num1,op,num2).orElseThrow(() -> new IllegalArgumentException("INVALID OPERATOR")));
I suggest returning always String.
public static String calc(double num1, String op, double num2){
if (op == "+") {
return String.valueOf(num1 + num2);
}
else if (op == "-") {
return String.valueOf(num1 - num2);
}
else if (op == "*") {
return String.valueOf(num1 * num2);
}
else if (op == "/") {
return String.valueOf(num1 / num2);
}
else {
return ("INVALID OPERATOR");
}
}

How to get a looping program in Java

I am new to Java programming and I wanted to try to make a calculator. I made the code, but the only problem is that it will only run once. I was wondering if there was any way to get it to "loop". By that I mean, add a question to go to the beginning of the main method that way I can run the calculator again. Here is the code I have...
import java.util.Scanner;
public class calculatorFull {
public static void main(String[] args){
int op;
double num1, num2;
Scanner operation = new Scanner(System.in);
System.out.println("1 - Add\n2 - Subtract\n3 - Multiply\n4 - Divide");
System.out.print("Which operation would you like to perform? ");
op = operation.nextInt();
if((op != 1) && (op != 2) && (op != 3) && (op != 4)){
System.out.println("That wasn't an option...");
}else{
System.out.print("First number: ");
num1 = operation.nextDouble();
System.out.print("Second number: ");
num2 = operation.nextDouble();
if(op==1){
Add(num1, num2);
}else if(op==2){
Sub(num1, num2);
}else if(op==3){
Mult(num1, num2);
}else if(op==4){
Div(num1, num2);
}
}
}
public static void Add(double x, double y){
double numsum;
numsum = x + y;
System.out.printf("%s + %s = %s", x, y, numsum);
}
public static void Sub(double x, double y){
double numsum;
numsum = x - y;
System.out.printf("%s - %s = %s", x, y, numsum);
}
public static void Mult(double x, double y){
double numsum;
numsum = x * y;
System.out.printf("%s * %s = %s", x, y, numsum);
}
public static void Div(double x, double y){
double numsum;
numsum = x / y;
System.out.printf("%s / %s = %s", x, y, numsum);
}
}
Thanks in advance for the help!
Btw, I think this might be different from this question (User input to repeat program in Java). I have different methods that I call from and that was changed to call from the main to just 1 method. Don't know if that changes any of the solutions or if it is the same problem but thank you for pointing out that it might be.
You can set a sentinel value to exit the program (i.e., -1 in your option) and keep track of a variable that we will constantly check in a while loop. If op ever becomes -1, it exits. Otherwise, it will restart the logic inside the while loop.
int op = 0;
while(op != -1) {
double num1, num2;
Scanner operation = new Scanner(System.in);
System.out.println("1 - Add\n2 - Subtract\n3 - Multiply\n4 - Divide");
System.out.print("Which operation would you like to perform? ");
op = operation.nextInt();
if((op != 1) && (op != 2) && (op != 3) && (op != 4)){
System.out.println("That wasn't an option...");
}else{
System.out.print("First number: ");
num1 = operation.nextDouble();
System.out.print("Second number: ");
num2 = operation.nextDouble();
if(op==1){
Add(num1, num2);
}else if(op==2){
Sub(num1, num2);
}else if(op==3){
Mult(num1, num2);
}else if(op==4){
Div(num1, num2);
}
}
int continue = 0;
while(continue == 0){
// Put your calculator code here
System.out.println("Enter 1 to exit or 0 to continue");
choice = Integer.parseInt(br.readLine());
}
Try this.
UPDATE:
Use this:
import java.io.*;
public class StackOverFlow
{
// arguments are passed using the text field below this editor
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int cont = 0;
while(cont == 0){
System.out.println("Inside");
// Put your calculator code here
System.out.println("Enter 1 to exit or 0 to continue");
cont = Integer.parseInt(br.readLine());
}
System.out.println("Outside");
}
}
The simplest way to do this, is to just call the main method when the calculation is complete and printed. You can achieve this by using main(null). Just add it right after your if-else block. Code below:
if(op==1){
Add(num1, num2);
}else if(op==2){
Sub(num1, num2);
}else if(op==3){
Mult(num1, num2);
}else if(op==4){
Div(num1, num2);
}
System.out.println(); // prints blank line
main(null);// calls main method (re-runs program)
This will complete the operation, then repeat the process.

A Memory Calculator Program

I have this program that asks user to enter a value and it calculates it as the user like to initial value of zero, then it ask the user what process to do again and ask the user to enter a value again and it calculates it to the last value of the instance, the problem is every time it asks the user to enter value it calculates it to zero not to the last entry. Please help me find the bug:
The program has to has two classes, one for the calculator and the other for the methods:
FIRST CLASS
public class MainClass {
public static void main(String[] args) {
MemoryCalculator calc = new MemoryCalculator();
calc.getCurrentValue();
displayMenu();
}
public static int displayMenu() {
Scanner input = new Scanner(System.in);
int choice;
do {
System.out.println("Menu");
System.out.println("1.Add");
System.out.println("2.Subtract");
System.out.println("3.Multiply");
System.out.println("4.Divide");
System.out.println("5.Clear");
System.out.println("6.Quit");
System.out.println("");
System.out.println("What would you like to do?");
choice = input.nextInt();
if (choice > 6 || choice < 1) {
System.out.println("Sorry," + choice + " was not an option");
return displayMenu();
}
} while (choice > 6 || choice < 1);
MemoryCalculator calc = new MemoryCalculator();
if (choice == 5) {
calc.clear();
return 0;
} else if (choice == 6) {
System.out.println("Goodbye! ");
System.exit(0);
}
System.out.println("What is the second number? ");
double operand2 = input.nextDouble();
switch (choice) {
case 1:
calc.add(operand2);
break;
case 2:
calc.subtract(operand2);
break;
case 3:
calc.multiply(operand2);
break;
case 4:
calc.divide(operand2);
break;
}
return displayMenu();
}
public static double getOperand(String prompt) {
return 0;
}
}
SECOND CLASS
public class MemoryCalculator {
private double currentValue;
public double getCurrentValue() {
System.out.println("The current value is " + currentValue);
return 0;
}
public void add(double operand2) {
currentValue = currentValue + operand2;
getCurrentValue();
}
public void subtract(double operand2) {
currentValue -= operand2;
getCurrentValue();
}
public void multiply(double operand2) {
currentValue *= operand2;
getCurrentValue();
}
public void divide(double operand2) {
if (operand2 == 0) {
System.out.println("Sorry, you can not divide by 0");
}
currentValue /= operand2;
getCurrentValue();
}
public void clear() {
currentValue = 0;
getCurrentValue();
}
}
You probably want to keep the last value stored in "calc". I see 3 bugs.
Move this line before the start of your "do" loop. This will keep it from reseting the value inside this variable/class.
MemoryCalculator calc = new MemoryCalculator();
Move your ending "while" loop line to the bottom of your method(right before the return statement). It only appears to be working because in your return statement you are calling your method again...see #3. Also you will want to change the "or" to the "and" operator in the while statement "choice>6 && choice<1"
}while(choice>6 && choice<1);
In you displayMenu method change the return statement, because you don't want it to call itself in an infinite loop... now that the do while loop is fixed.
return displayMenu();
to this
return choice;

Java: Subclass can't get value of field in superclass

Here's the superclass:
public class MemoryCalc {
private double currentValue;
public double getCurrentValue() {
return currentValue;
}
public void setCurrentValue(double currentValue) {
this.currentValue = currentValue;
}
public int displayMenu() {
#SuppressWarnings("resource")
Scanner input = new Scanner(System.in);
int choice = -1;
while (choice < 1 || choice > 6) {
System.out.println();
System.out.println("Menu");
System.out.println("1. Add");
System.out.println("2. Subtract");
System.out.println("3. Multiply");
System.out.println("4. Divide");
System.out.println("5. Clear");
System.out.println("6. Quit");
System.out.println();
System.out.print("What would you like to do? ");
choice = input.nextInt();
if (choice < 1 || choice > 6) {
System.out.println(choice + " wasn't one of the options");
}
if (choice == 6) {
System.out.println("Goodbye!");
System.exit(0);
}
}
return choice;
}
public double getOperand(String prompt) {
#SuppressWarnings("resource")
Scanner input = new Scanner(System.in);
System.out.print(prompt);
return input.nextDouble();
}
public void add(double op2) {
currentValue += op2;
}
public void subtract(double op2) {
currentValue -= op2;
}
public void multiply(double op2) {
currentValue *= op2;
}
public void divide(double op2) {
if (op2 == 0) {
currentValue = Double.NaN;
} else {
currentValue /= op2;
}
}
public void clear() {
currentValue = 0;
}
}
Here's the Subclass:
class SciMemCalc extends MemoryCalc{
private double currentValue;
public int displayMenu(){
#SuppressWarnings("resource")
Scanner input = new Scanner(System.in);
int choice = -1;
while (choice < 1|| choice > 8){
System.out.println();
System.out.println("Menu:");
System.out.println("1. Add");
System.out.println("2. Subtract");
System.out.println("3. Multiply");
System.out.println("4. Divide");
System.out.println("5. Power");
System.out.println("6. Logarithm");
System.out.println("7. Clear");
System.out.println("8. Quit");
System.out.println();
System.out.println("What would you like to do?");
choice = input.nextInt();
if (choice < 1|| choice > 8){
System.out.println(choice +" wasn't one of the options");
}
if (choice == 8){
System.out.println("Thank you, good bye!");
System.exit(0);
}
}
return choice;
}
public void power(double op2){
Math.pow(currentValue, op2);
}
public void log() {
Math.log(currentValue);
}
}
Here's the Driver:
public class SciCalcDriver {
public static void main(String[] args) {
SciMemCalc calc = new SciMemCalc();
while (true){
System.out.println("The current value is " + calc.getCurrentValue());
int choice = calc.displayMenu();
double second = 0;
if (choice < 6) {
second = calc.getOperand("What is the second number? ");
}
if (choice == 1) {
calc.add(second);
} else if (choice == 2){
calc.subtract(second);
} else if (choice == 3){
calc.multiply(second);
} else if (choice == 4){
calc.divide(second);
} else if (choice == 5){
calc.power(second);
} else if (choice == 6){
calc.log();
} else if (choice == 7){
calc.clear();
}
}
}
}
Now the calculator can add, subtract, multiply, and divide fine but when I use the power or log method nothing happens. I've tried using the debugger and it says it get's all the necessary inputs, but the currentValue doesn't seem to change. I don't think I need to make any changes to the superclass. Advice?
class MemoryCalc {
private double currentValue;
}
class SciMemCalc extends MemoryCalc {
private double currentValue;
}
What is happening here is there are actually two variables declared with the same name. SciMemCalc does not have access to the variable declared in MemoryCalc because it is private.
Instead you would normally make currentValue protected or interact with it through setters and getters.
class MemoryCalc {
protected double currentValue;
}
class SciMemCalc extends MemoryCalc {
// SciMemCalc has access to currentValue
}
Remove private double currentValue; from the subclass and change private double currentValue; in the superclass to protected double currentValue;. If you have a private value, it can't be accessed by the superclass, and the duplicate value you have created just hides the original. Protected solves this.
You're shadowing your superclass' currentValue by re-declaring it in your subclass. To resolve the issue, in your subclass SciMemCalc, get rid of the line declaring currentValue:
private double currentValue;
And change all of SciMemCalc's accesses to currentValue to use the superclass' accessor (getter) and mutator (setter) methods:
public void power(double op2){
setCurrentValue(Math.pow(getCurrentValue(), op2));
}
public void log() {
setCurrentValue(Math.log(getCurrentValue()));
}
Alternatively, you could declare currentValue as protected in your superclass which would allow you to access it directly in your subclass. However, also in this case, you have to make sure that you assign the result of your calculation back to currentValue:
public void power(double op2){
currentValue = Math.pow(currentValue, op2);
}
public void log() {
currentValue = Math.log(currentValue);
}
You have declared the currentValue as a private member of class so it cannot be accessed by other
classes. when you make it protected or public then it will work. And will solve you problem.
just change that currentValue field in super class.
protected double currentValue // it will be only accessed by its child class
public double currentValue // it will be accessed by all classes in this package

Error in simple java program

I am working on teaching myself java and while working on a code using classes I ran into this error
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at java.util.Scanner.nextDouble(Unknown Source)
at StateCalculator.getOperand(StateCalculator.java:29)
at StateCalculator.main(StateCalculator.java:77)
Below is my code:
import java.util.Scanner;
public class StateCalculator {
private double currentValue = 0;
//Initialize to 0
public StateCalculator() {
}
public static int displayMenu() {
Scanner keyboard = new Scanner(System.in);
int menuChoice = 0;
do {
System.out.print("Menu\n 1. Add\n 2. Subtract\n 3. Multiply\n 4. Divide\n 5.Clear\n 6. Quit\n What would you like to do?: ");
menuChoice = keyboard.nextInt();
} while(menuChoice < 1 || menuChoice > 6);
keyboard.close();
return menuChoice;
}
public static double getOperand(String prompt) {
Scanner input = new Scanner(System.in);
double operand = 0;
System.out.print(prompt);
operand = input.nextDouble();
input.close();
return operand;
}
public double getCurrentValue() {
return currentValue;
}
public void add(double operand) {
currentValue += operand;
}
public void subtract(double operand) {
currentValue -= operand;
}
public void multiply(double operand) {
currentValue *= operand;
}
public void divide(double operand) {
if(operand == 0) {
currentValue = Double.NaN;
}
else {
currentValue /= operand;
}
}
public void clear() {
currentValue = 0;
}
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
StateCalculator calculator = new StateCalculator();
int option;
double operand;
do{
System.out.println("The current value is " + calculator.currentValue);
option = StateCalculator.displayMenu();
switch(option) {
case 1:
operand = getOperand("What is the second number?: ");
calculator.add(operand);
break;
case 2:
operand = getOperand("What is the second number?: ");
calculator.subtract(operand);
break;
case 3:
operand = getOperand("What is the second number?: ");
calculator.multiply(operand);
break;
case 4:
operand = getOperand("What is the second number?: ");
calculator.divide(operand);
break;
case 5:
calculator.clear();
break;
}
}while(option != 6);
keyboard.close();
}
}
I tried running the debug feature in eclipse and discovered the problem occurs on line 29 in my getOperand method when I attempt to set operand = input.nextDouble. However, I don't understand why this would be an issue.
Don't call keyboard.close(); when you close keyboard (which you defined)
Scanner keyboard = new Scanner(System.in);
it closes System.in, and then your other methods can't work (because the console will not re-open). You can have multiple scanners on System.in (as long as you don't close them), or pass one (or, but please don't, use a global).
Per the javadoc,
When a Scanner is closed, it will close its input source if the source implements the Closeable interface.

Categories