0

我的代码有问题。这是我们的任务:

“编写一个名为 clsWorker 的超类以及 clsHourlyWorker 和 clsSalariedWorker 的子类。每个工人都有一个姓名和工资率。编写一个计算每个工人每周工资的方法 computePay(int hours)。一个小时工获得实际工资的小时工资如果小时数最多为 40 小时。如果小时工工作时间超过 40 小时,超出的部分按时间支付一半。工薪工人获得 40 小时的小时工资,无论实际数字是多少小时数是。写一个继承的测试程序。输入工人的姓名,工作小时数和工人的类型,H代表每小时,S代表工资,工人的工资率。显示每个人的工资工人进来了。”

我们需要做覆盖和继承。我总是遇到 NoSuchMethodError

我的超类:

     public class clsWorker
{   
    int hours=0,excess=0;
    double salary,newSalary=0.0;
    String sType;


    public clsWorker()
    {

    }

    public clsWorker(double sal,String type)
    {
        //this.hours=hours;
        salary=sal;
        sType=type;
    }

    public double computePay(int hours)
    {   
        sType=sType.toUpperCase();
        if(sType.equals("H"))       
        newSalary=(salary*hours)*7;
        else if(sType.equals("S"))
        {   if(hours>=40)
            newSalary=salary*40;
            else if(hours>40)
            {
            excess=hours-40;
            newSalary=(newSalary+((newSalary*excess)*1.5))*7;
            }
        }
        return newSalary;       
    }


}

我的子类

public class clsHourlyWorker extends clsWorker
    {   
        double dSalary=0.0;
        int iHours=0;

        public clsHourlyWorker()
        {
            //super();
        }

        public clsHourlyWorker(int iHours, double salaryph,String sRate)
        {

            super(iHours,salaryph,sRate);   
            //clsWorker w=new clsWorker();
            dSalary=newSalary;  

        }




        public double getSalary()
        {
            return dSalary;
        }
    }

public class clsSalariedWorker extends clsWorker
{
    double dSalary=0.0;
    int iHours=0;   

    public clsSalariedWorker()
    {
        //super();
    }

    public clsSalariedWorker(int iHours,double salaryph,String sRate)
    {

        super(iHours,salaryph,sRate);
        //super(salaryph,sRate);
        //this.iHours=iHours;   
        //clsWorker w=new clsWorker();
        dSalary=newSalary;
    }

    /*public void setSalary(int iHourjs)
    {

    }*/ 

    public double getSalary()
    {
        return dSalary;
    }
}

我的测试课

import java.util.*;

public class testSalary
{

    public static void main(String[]args)
    {


        Scanner console=new Scanner(System.in); 

        System.out.println("Input Salary per hour: ");
        double salaryph=console.nextDouble();
        System.out.println("Input number of hours: ");
        int iHours=console.nextInt();
        console.nextLine();
        System.out.println("Input Worker Name: ");
        String sName=console.nextLine();
        System.out.println("Input Type of Worker: ");
        String sRate=console.next();


        clsHourlyWorker hw=new clsHourlyWorker(iHours,salaryph,sRate);
        clsSalariedWorker sw=new clsSalariedWorker(iHours,salaryph,sRate);

        //System.out.println("Worker Name: "+sName+"\nSalary: "+hw.getSalary());
        if(sRate.equals("H"))
        System.out.println("Worker Name: "+sName+"\nSalary: "+hw.getSalary());
        else if (sRate.equals("S"))
        System.out.println("Worker Name: "+sName+"\nSalary: "+sw.getSalary());


    }

}

有人可以告诉我如何解决我的问题吗?谢谢。

4

2 回答 2

2

This doesn't make sense:

    public clsHourlyWorker(int iHours, double salaryph,String sRate)
    {

        super(iHours,salaryph,sRate);   
        //clsWorker w=new clsWorker();
        dSalary=newSalary;  

    }

Since the super class's constructor doesn't take int, double, and String but rather, it takes String, double, int representing name, dRate, and hours. Also is sRate really supposed to be a String? I strongly doubt it.

I suggest that your child class constructor accept in the parameter all the information needed for the super constructor (a Strinng for name, double for dRate and int for hours) plus additional parameters the additional information for the new child class fields. You may wish to re-think those fields though as some seem to be duplicates of the super's fields and thus unnecessary.

于 2013-09-05T18:30:11.743 回答
2

有几点可以改进:

使用继承

简而言之,您发布的代码根本没有利用继承的力量。您创建了两个子类,但它们所做的只是将支付计算委托给超类。在子类中clsWorker进行抽象、computePay抽象和实现方法的两个不同版本:

public abstract class Worker {
    // ...
    public abstract double computePay(int hours);
}

public class HourlyWorker extends Worker {
    // ...
    @Override
    public double computePay(int hours) {
        // code from the 'sType.equals("H")' block
    }
}

public class SalariedWorker extends Worker {
    // ...
    @Override
    public double computePay(int hours) {
        // code from the 'sType.equals("S")' block
    }
}

现在你也会意识到这个领域sType没有任何有用的目的。事实上,只有在 Java 不支持多态性时才需要这种方法。您已经知道(在编写代码时)您是在处理 HourlyWorker 还是 SalriedWorker,因为您将代码放在HourlyWorker'scomputePaySalariedWorker's中computePay

sType不提供任何通过查看继承层次结构我们不会知道的新信息。这样,您将两次提供完全相同的信息(一次通过继承,一次通过sType),这是我们在软件开发中通常试图避免的事情。

改进“测试”类

(我将“test”放在引号中,因为大多数开发人员会认为“test”类是指某种自动化的、单元测试的“test”——例如 JUnit 测试用例。)

第一件看起来很奇怪的事情是:如果用户可以选择创建一个 HourlyWorkernew clsHourlyWorker一个 SalriedWorker(但不能同时创建,这是“排他性的”),为什么还要实例化一个 HourlyWorker 和一个 SalariedWorker(即, )?new clsSalariedWorker

您真正想要的是以下内容:

    Worker w;
    if(sRate.equals("H"))
        w = new HourlyWorker(iHours,salaryph);
    else if (sRate.equals("S"))
        w = new SalariedWorker(iHours,salaryph);
    else
        throw new Exception("Don't recognize worker type: " + sRate);

    System.out.println("Worker Name: "+sName+"\nSalary: "+w.getSalary());

如您所见,使用抽象超类Worker作为您的工作实例变量的类型是有效的w,如果您此时(在运行时)不知道用户是否会选择HS。您只需要访问getSalary在中声明的访问Worker,所以一切都很好。(如果您以后需要访问仅由子类实现的方法,您仍然可以对它进行类型转换。)

您还将意识到您只需要一个println. 同样,我们希望尽量减少重复以支持抽象。这两行基本相同,它们打印工人的姓名和计算的工资,所以我们尝试将两行减少为一行,更抽象的代码行。

其次,您可能还不想直接打印,而是sName希望getNameWorker. 当您开始处理较大的项目时,您会发现输入和输出可能发生在非常不同的时间和地点(例如,Worker可能存储在数据库中,sName当不同的用户Worker从数据库)。因此,请准备好从您的真实对象中获取所有必需的数据,而不是测试输入。

第三——但我在这里可能弄错了——“显示输入的每个工人的工资”对我来说听起来就像你应该实现一个while用户可以输入多个工人的循环。但是,您可以从这项作业中学到更重要的东西。

遵循命名约定

在 Java 中,使用大写的类名和小写的方法名是很常见的做法。通常你会有 Worker、HourlyWorker 和 SalriedWorker(参见上面的代码示例)。这样,世界上的每个 Java 开发人员都可以知道我们在谈论类。

但是,对于您的任务,我建议您遵循任何任意的“约定”——请记住,这不是标准的 Java 方式。在实际项目中执行此类操作之前,请阅读命名约定(一般和特定)。

于 2013-09-05T19:48:18.300 回答