【问题标题】:Java - Field in parent class not changingJava - 父类中的字段不变
【发布时间】:2018-11-02 22:49:50
【问题描述】:

所以,我在父类中有一个变量,我试图在子类中使用 getter/setter 方法进行更改。但是,价值只是保持不变,我不知道为什么..我做错了什么?任何帮助表示赞赏!

  • 下面是程序的细分: 在驱动程序类中,您选择要执行的操作,然后它使用当前值变量和您选择的数字(操作数 2)来获得答案。加法、减法、乘法和除法在内存计算器类中。它也可以清除,将当前值变量设置为零。现在,我们正在向它添加一个子类,用于计算指数和对数。

  • 细节:当我尝试使用 ScientificMemCalc 类中的 power 或 log 方法时,MemoryCalc 类中的变量 currentValue 保持不变。在该类中,它使用 getter 方法获取当前值,然后尝试使用 setter 方法更改当前值。但没有任何改变。还有一个问题:getter 方法从 currentValue 字段中获取零值。

这里是带有 main 方法的驱动类:

package ScientificMemCalc;

import java.util.Scanner;

import ScientificMemCalc.MemoryCalc;

public class ScientificCalcDriver {

    public static void main(String[] args) {

    Scanner input = new Scanner(System.in);

    MemoryCalc calculator = new MemoryCalc();
    ScientificMemCalc scientificCalc = new ScientificMemCalc();


    int menu = 0;
    double operand2, answer;

    while (menu !=8) {

        answer = calculator.getCurrentValue();
        System.out.println("The current value is: " + answer);  

        menu = getMenuOption();

        switch(menu) {
        case 1:
            // Add
            operand2 = calculator.getOperand("What is the second number?: ");
            calculator.add(operand2);
            break;

        case 2:
            // Subtract
            operand2 = calculator.getOperand("What is the second number?: ");
            calculator.subtract(operand2);
            break;

        case 3:
            // Multiply
            operand2 = calculator.getOperand("What is the second number?: ");
            calculator.multiply(operand2);
            break;

        case 4:
            // Divide
            operand2 = calculator.getOperand("What is the second number?: ");
            calculator.divide(operand2);
            break;

        case 5:
            // Power
            operand2 = calculator.getOperand("What is the second number?: ");
            scientificCalc.power(operand2);
            break;

        case 6:
            // Logarithm
            scientificCalc.log();
            break;

        case 7:
            // Clear
            operand2 = 0;
            calculator.clear();
            break;

        case 8:
            // Quit
            System.out.println("Goodbye!");
            break;
        }
    }
}

public static int getMenuOption() {

    Scanner input = new Scanner(System.in); 

    int choice = 0;

    // Display menu
    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");

    // Get menu input
    System.out.print("What would you like to do?: ");
    choice = input.nextInt();

    while (choice < 1 || choice > 8) {
        System.out.print("Invalid. Try again: ");
        choice = input.nextInt();
    }

    return choice;
    }
}

这里是内存计算器类:

package ScientificMemCalc;

import java.util.Scanner;

public class MemoryCalc {

private double currentValue;

public double getOperand(String prompt) {

    Scanner input = new Scanner(System.in);

    System.out.print(prompt);
    return input.nextDouble();

}
public double getCurrentValue() {
    return currentValue;
}
public void setCurrentValue(double temp) {
    currentValue = temp;
}
public void add(double operand2) {
    // Add
    currentValue += operand2;
}
public void subtract(double operand2) {
    // Subtract
    currentValue -= operand2;
}
public void multiply(double operand2) {
    // Multiply
    currentValue *= operand2;
}
public void divide(double operand2) {
    // Divide
    if (operand2 == 0) {
        System.out.println("You cannot divide by zero!");
        currentValue = Double.NaN;
    }
    else {
        currentValue /= operand2;
    }
}
public void clear() {
    // Clear
    currentValue = 0;

    }
}

最后是添加科学功能的子类:

package ScientificMemCalc;

public class ScientificMemCalc extends MemoryCalc {

public void power(double operand2) {
    // Power
    double currentValue = getCurrentValue();
    double temp = Math.pow(currentValue, operand2);
    setCurrentValue(temp);
}
public void log() {
    // Logarithm
    double currentValue = getCurrentValue();
    double temp = Math.log(currentValue);
    setCurrentValue(temp);
    }

}

【问题讨论】:

  • 有多个对象,每个对象都有自己的自己的 currentValue 实例字段。从实例离散继承:calculator,一个对象,scientificCalc,另一个具有自己的字段的对象。无论继承如何,对一个对象的更改都不会直接影响另一个对象。 (static 字段是另一个主题;它们也不是继承的,但在 Java 中具有奇怪的访问行为..)
  • 解决此问题的一种方法可能是拥有一个 CalculatorState 类,例如,该类将包含 currentValue 并可以访问此类。然后:s = new CalculatorState(); c1 = new Calculator(s); c2 = new SuperCoolCalculator(s);。现在两个计算器实例共享​​>一个他们可以修改的公共状态实例(“s”)。
  • 我不清楚最后一条评论中的上下文/错误:} 什么“说”“未定义”?
  • 感谢您的帮助!这是有道理的,为什么它的价值保持不变。是否可以在不添加其他类的情况下进行修复?它是一项任务,我们只能拥有那些......我最初所做的是例如“calculator.power(operand2);”但随后它说计算器对象的幂方法未定义。现在我知道发生了什么,一个更好的问题是:我可以通过计算器对象访问子类 power 和 log 方法吗? @user2864740
  • 在这种特殊情况下,您可以使用scientificCalc 对象进行所有计算。 ScientificMemCalc 扩展了 MemoryCalc 所以它继承了父级的方法。

标签: java eclipse class object inheritance


【解决方案1】:

简答

您正在与两个不同的对象 calculatorscientificCalc 进行交互。它们不共享任何状态。

你能做什么?

  1. 使用scientificCalc 进行所有计算。因此,该值将是唯一的。

缺点:一旦你引入其他计算器类型,事情就会变得更加复杂

  1. calculator 作为构造函数参数传递给ScientificMemCalc 的构造函数。

缺点:与 #1 相同

  1. 使用单独的类/对象来存储状态。 (由@user2864740 建议)

  2. 不要将状态存储在计算器中(为什么需要它?)。将所有操作数(当前状态将始终是操作数 #1)传递给方法并将结果返回给调用者:

    int menu = 0;
    double operand2, answer;
    while (menu !=8) {
    
        // You don't need this line
        //answer = calculator.getCurrentValue();
    
        System.out.println("The current value is: " + answer);  
    
        menu = getMenuOption();
    
        switch(menu) {
        case 1:
            // Add
            operand2 = calculator.getOperand("What is the second number?: ");
            // 
            answer = calculator.add(answer, operand2);
            break;
            //... modify other operations in the same way
    }
    

【讨论】:

    【解决方案2】:

    在您扩展 MemoryCalc 的 ScientificMemCalc 类中,这允许 ScientificMemCalc 调用在 MemoryCalc 中创建的方法,并提供对其在 MemoryCalc 中自己的变量集的访问。但是,当为每个类创建两个单独的对象时,它们都可以访问同名和类型的变量,但它们将是两个单独对象中的两个单独变量。

    一种解决方案是将 MemoryCalc 对象传入 ScientificMemCalc 类的构造函数,然后针对该对象调用 getCurrentValue()/setCurrentValue() 方法。允许访问同一个变量。

    package scientificMemCalc;
    
    public class ScientificMemCalc {
    
        //store the MemoryCalc object so we have access to the needed data
        private MemoryCalc memCalc;
    
        //store the MemoryCalc
        public ScientificMemCalc(MemoryCalc memCalc) {
            this.memCalc = memCalc;
        }
    
        public void power(double operand2) {
    
            // Power
            double currentValue = memCalc.getCurrentValue();
            double temp = Math.pow(currentValue, operand2);
            memCalc.setCurrentValue(temp);
    
        }
    
        public void log() {
    
            // Logarithm
            double currentValue = memCalc.getCurrentValue();
            double temp = Math.log(currentValue);
            memCalc.setCurrentValue(temp);
    
        }
    
    }
    

    然后在实例化 ScientificMemCalc 对象时传入 MemoryCalc 的引用。

    MemoryCalc calculator = new MemoryCalc();
    ScientificMemCalc scientificCalc = new ScientificMemCalc(calculator);
    

    希望这会有所帮助!

    【讨论】:

    • 你打赌!乐于助人!
    • 包名应始终为小写
    猜你喜欢
    • 2014-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    相关资源
    最近更新 更多