覆盖和继承

时间:2013-09-05 18:27:05

标签: java inheritance

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

  

“写一个名为clsWorker的超类和子类clsHourlyWorker和clsSalariedWorker。每个工人都有一个名字和工资率。写一个方法computePay(int hours)计算每个工人的每周工资。每小时工人得到小时工资如果小时数最多为40小时,则实际工作小时数为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());


    }

}

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

2 个答案:

答案 0 :(得分:2)

这没有意义:

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

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

    }

由于超类的构造函数不接受int,double和String,而是采用String,double,int表示name,dRate和hours。 sRate真的应该是 String 吗?我强烈怀疑。

我建议您的子类构造函数在参数中接受超级构造函数所需的所有信息(名称为Strinng,dRate为double,小时为int)以及其他参数新子类字段的附加信息。您可能希望重新考虑这些字段,因为有些字段似乎与超级字段重复,因此是不必要的。

答案 1 :(得分: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还是SalariedWorker,因为您将代码放在HourlyWorker的{​​{1}}或computePay的{​​{{ 1}}。

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

改进“测试”类

(我把“测试”放在引号中,因为大多数开发人员认为通过“测试”类,你的意思是某种自动化的单元测试“测试” - 例如JUnit测试用例。)

首先看起来奇怪的是:如果用户可以选择创建HourlyWorker 或sType,sType) >之前的SalariedWorker(但不是两者,这是'独家或')?

你真正想要的是:

new clsHourlyWorker

正如您所看到的,如果此时(运行时)不知道是否将抽象超类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()); 的类型是有效的用户将选择Workerw。您只需要访问H中声明的S,这样就可以了。 (如果您以后需要访问仅由子类实现的方法,您仍然可以键入它。)

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

其次,您也可以直接打印Worker,而不想在println中使用吸气剂(sName)。当您开始处理大型项目时,您会看到输入和输出可能在非常不同的时间和地点发生(例如getName可能存储在数据库中,原始变量Worker将是一个不同的用户从数据库中检索Worker时已经过去了。因此,请准备好从您的真实对象获取所有必需的数据,而不是测试输入。

第三 - 但我可能会在这里弄错了 - “显示每个工作人员输入的工资”听起来对我来说就像你应该实现一个sName循环,用户可以进入多个工人。但是,你可以从这项任务中学到更多重要的事情。

遵循命名约定

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

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