Java 重写和继承
我的代码有问题。这是我们的任务: “编写一个名为clsWorker的超类和子类clsHourlyWorker和clsSalariedWorker。每个工人都有一个名字和工资率。编写一个方法computePay(整数小时)这将计算每个工人的周工资。如果小时数最多为40小时,则小时工将获得实际工作小时数的小时工资。如果小时工工作时间超过40小时,则超额部分将按时间半支付。受薪工人将获得40小时的小时工资,无论实际工作小时数是多少。为继承编写一个测试程序。输入工人的姓名、工作小时数和工人类型,H代表小时,S代表工薪,工人的工资率。显示输入的每个工人的工资。” 我们需要进行覆盖和继承。我总是遇到错误 我的超类:Java 重写和继承,java,inheritance,Java,Inheritance,我的代码有问题。这是我们的任务: “编写一个名为clsWorker的超类和子类clsHourlyWorker和clsSalariedWorker。每个工人都有一个名字和工资率。编写一个方法computePay(整数小时)这将计算每个工人的周工资。如果小时数最多为40小时,则小时工将获得实际工作小时数的小时工资。如果小时工工作时间超过40小时,则超额部分将按时间半支付。受薪工人将获得40小时的小时工资,无论实际工作小时数是多少。为继承编写一个测试程序。输入工人的姓名、工作小时数和工人类型,H代表小
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());
}
}
有人能告诉我如何解决我的问题吗?谢谢。这没有意义:
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真的应该是一个字符串吗?我对此深表怀疑
我建议您的子类构造函数在参数中接受超级构造函数所需的所有信息(Strinng表示name,double表示dRate,int表示hours),再加上附加参数,即新子类字段的附加信息。您可能希望重新考虑这些字段,因为有些字段似乎与super的字段重复,因此不必要。这没有意义:
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真的应该是一个字符串吗?我对此深表怀疑
我建议您的子类构造函数在参数中接受超级构造函数所需的所有信息(Strinng表示name,double表示dRate,int表示hours),再加上附加参数,即新子类字段的附加信息。您可能希望重新考虑这些字段,因为其中一些字段似乎与super的字段重复,因此不必要。可以改进以下几点: 使用继承 简单地说,您发布的代码根本没有利用继承的功能。您创建了两个子类,但它们所做的只是将付款计算委托给超类。将
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
的computePay
或受薪工的computePay
中
sType
不提供任何我们在查看继承层次结构时无法了解的新信息。这样,您将两次提供完全相同的信息(一次是通过继承,一次是通过sType
),这是我们在软件开发中通常试图避免的
改进“测试”类
(我在引号中加上了“test”,因为大多数开发人员会认为,“test”类是指某种自动化的单元测试“test”——例如JUnit测试用例。)
第一件看起来很奇怪的事情是:如果用户可以选择在之前创建HourlyWorker或SalariedWorker(但不能同时创建两者,这是“独占”或“独占”),那么为什么要同时实例化HourlyWorker和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());
如您所见,如果此时(在运行时)您不知道用户是选择H
还是S
,那么使用抽象超类Worker
作为Worker实例变量w
的类型是有效的。您只需要访问getSalary
,它在Worker
中声明,所以一切都很好。(如果以后需要访问仅由子类实现的方法,仍然可以键入cast。)
您还将认识到,您只需要一个println
。同样,我们希望尽量减少重复,以利于抽象。这两行基本上是一样的,它们打印一个工人的姓名和计算的工资,所以我们尝试将两行代码减少为一行更抽象的代码
其次,您可能也不想直接打印sName
,而是想在Worker
中有一个getter(getName
)。当您着手处理更大的项目时,您会发现输入和输出可能发生在非常不同的时间和地点(例如,Worker
可能存储在数据库中,当不同的用户从数据库检索Worker
时,原始变量sName
将消失很久)。因此,准备好从真实对象中获取所有必需的数据,而不是测试输入
第三,但我可能弄错了——“显示输入的每个工人的工资”听起来像是您应该实现一个while
循环,用户可以输入多个工人。但是,你可以从这次作业中学到更多重要的东西
遵循命名约定
在Java中,通常使用大写的类名和小写的方法名。通常您会有Worker、HourlyWorker和salarydworker(参见上面的代码示例)。这样,世界上的每个Java开发人员都可以知道我们在谈论类
然而,f