在摘要 class 中返回 object 的解决方法
Workaround for returning object in abstract class
我正在为学校制定薪资计划,并有薪资 driver、员工 class、每小时 class(扩展员工)、Salaried
class(扩展雇员)和 SalariedPlusCommission
class(扩展受薪)。下面的代码是 Employee object 和来自 Employee 的 load()
方法(也是每个子 class 中的 load()
方法)。我必须有一个抽象方法 getEarnings()
所以整个 Employee class 是抽象的。我收到一个错误 "Employee is abstract; cannot be instantiated"。我明白为什么我会收到错误,但我不知道如何将信息输入我的员工 object。
public Employee(String name, String socialSecurityNumber, int month, int week)
{
this.name=name;
this.socialSecurityNumber=socialSecurityNumber;
this.month=month;
this.week=week;
}
public static Employee load()
{
Scanner stdIn = new Scanner (System.in);
System.out.println("Name ==> ");
name=stdIn.nextLine();
System.out.println("Social Security Number ==>");
socialSecurityNumber=stdIn.nextLine();
System.out.println("Birthday Month '('1-12')' ==> ");
month=stdIn.nextInt();
System.out.println("Birthday Bonus Week '('1-4')' ==>");
week=stdIn.nextInt();
return new Employee(name, socialSecurityNumber, month, week);
}
如果这里有帮助,请使用 Hourly 的 Hourly object 和 load()
方法:
public Hourly(String name, String socialSecurityNumber, int month, int week, double hourlyPay, double hoursWorked)
{
super(name, socialSecurityNumber, month, week);
this.hourlyPay=hourlyPay;
this.hoursWorked=hoursWorked;
}
public static Hourly load()
{
Scanner stdIn = new Scanner (System.in);
System.out.println("Hourly Pay ==> ");
hourlyPay=stdIn.nextDouble();
System.out.println("Hours Worked This Past Week ==>");
hoursWorked=stdIn.nextDouble();
return new Hourly(name, socialSecurityNumber, month, week, hourlyPay, hoursWorked);
}
一旦将抽象方法添加到 class 中,就无法再实例化它。在您的方案中,如果 Hourly、Salaried 和 SalariedPlusCommission 提供了 getEarnings() 和 Employee 声明的任何其他抽象方法的实现,您可以实例化它们。
像这样的 class 层次结构的一个共同意图是使用 Employee 来保存所有子 class 共有的行为(代码)。你扩展它而不直接实例化它。
如果您确实需要实例化 Employee,那么您必须提供 getEarnings() 的实现,并且可能还覆盖每个子class 中的实现。如果您愿意,基本实现可以 return null 甚至抛出异常。拥有 NOOP 基础实现让我觉得很有潜力 "bad code smell",但我不知道您还想完成什么。
您也可以只使用该方法创建一个 IEarn 接口,并让每个子class 实现它(但不是 Employee)。这里的问题是,您将无法将所有实体声明为基础 class,以便在收入方面以多态方式处理它们。你将无法做到:
Employee foo = new Hourly();
Employee baz = new Salaried();
baz.getEarnings();
foo.getEarnings();
你必须做的:
IEarn foo = new Hourly();
IEarn baz = new Salaried();
baz.getEarnings();
foo.getEarnings();
但这里通常要做的事情是设计 class 层次结构,以便 Employee 可以用作抽象 class 而不会直接实例化。
Employee
是一个抽象class,这意味着它没有实现它的所有方法。 subclasses 以正确的行为实现这些方法。因此,加载 Employee
没有意义,而加载 Hourly
却有意义,因为它实现了所有方法。
您不应该尝试实例化员工。相反,从 Employee
class 中删除 load()
方法,只保留 Hourly
、Salaried
和 SalariedPlusCommission
load()
方法。
如果你需要为Employee
创建一个load()
方法,那么询问用户he/she想要什么样的员工:
System.out.println("Type (Hourly, Salaried or SalariedPlusCommission): ");
t=stdIn.nextLine();
switch(t) {
case "Hourly":
return Hourly.load()
break;
// other cases
}
但是请注意,这不是好的做法,Employee
class 不应负责实例化其子class。此要求涉及使用 Employee
的代码。例如,不应该要求 Employee
class 了解其所有子 class。使用 Employee
的代码有此责任,因为只有该代码才能知道它想要支持哪些员工子类型。
我正在为学校制定薪资计划,并有薪资 driver、员工 class、每小时 class(扩展员工)、Salaried
class(扩展雇员)和 SalariedPlusCommission
class(扩展受薪)。下面的代码是 Employee object 和来自 Employee 的 load()
方法(也是每个子 class 中的 load()
方法)。我必须有一个抽象方法 getEarnings()
所以整个 Employee class 是抽象的。我收到一个错误 "Employee is abstract; cannot be instantiated"。我明白为什么我会收到错误,但我不知道如何将信息输入我的员工 object。
public Employee(String name, String socialSecurityNumber, int month, int week)
{
this.name=name;
this.socialSecurityNumber=socialSecurityNumber;
this.month=month;
this.week=week;
}
public static Employee load()
{
Scanner stdIn = new Scanner (System.in);
System.out.println("Name ==> ");
name=stdIn.nextLine();
System.out.println("Social Security Number ==>");
socialSecurityNumber=stdIn.nextLine();
System.out.println("Birthday Month '('1-12')' ==> ");
month=stdIn.nextInt();
System.out.println("Birthday Bonus Week '('1-4')' ==>");
week=stdIn.nextInt();
return new Employee(name, socialSecurityNumber, month, week);
}
如果这里有帮助,请使用 Hourly 的 Hourly object 和 load()
方法:
public Hourly(String name, String socialSecurityNumber, int month, int week, double hourlyPay, double hoursWorked)
{
super(name, socialSecurityNumber, month, week);
this.hourlyPay=hourlyPay;
this.hoursWorked=hoursWorked;
}
public static Hourly load()
{
Scanner stdIn = new Scanner (System.in);
System.out.println("Hourly Pay ==> ");
hourlyPay=stdIn.nextDouble();
System.out.println("Hours Worked This Past Week ==>");
hoursWorked=stdIn.nextDouble();
return new Hourly(name, socialSecurityNumber, month, week, hourlyPay, hoursWorked);
}
一旦将抽象方法添加到 class 中,就无法再实例化它。在您的方案中,如果 Hourly、Salaried 和 SalariedPlusCommission 提供了 getEarnings() 和 Employee 声明的任何其他抽象方法的实现,您可以实例化它们。
像这样的 class 层次结构的一个共同意图是使用 Employee 来保存所有子 class 共有的行为(代码)。你扩展它而不直接实例化它。
如果您确实需要实例化 Employee,那么您必须提供 getEarnings() 的实现,并且可能还覆盖每个子class 中的实现。如果您愿意,基本实现可以 return null 甚至抛出异常。拥有 NOOP 基础实现让我觉得很有潜力 "bad code smell",但我不知道您还想完成什么。
您也可以只使用该方法创建一个 IEarn 接口,并让每个子class 实现它(但不是 Employee)。这里的问题是,您将无法将所有实体声明为基础 class,以便在收入方面以多态方式处理它们。你将无法做到:
Employee foo = new Hourly();
Employee baz = new Salaried();
baz.getEarnings();
foo.getEarnings();
你必须做的:
IEarn foo = new Hourly();
IEarn baz = new Salaried();
baz.getEarnings();
foo.getEarnings();
但这里通常要做的事情是设计 class 层次结构,以便 Employee 可以用作抽象 class 而不会直接实例化。
Employee
是一个抽象class,这意味着它没有实现它的所有方法。 subclasses 以正确的行为实现这些方法。因此,加载 Employee
没有意义,而加载 Hourly
却有意义,因为它实现了所有方法。
您不应该尝试实例化员工。相反,从 Employee
class 中删除 load()
方法,只保留 Hourly
、Salaried
和 SalariedPlusCommission
load()
方法。
如果你需要为Employee
创建一个load()
方法,那么询问用户he/she想要什么样的员工:
System.out.println("Type (Hourly, Salaried or SalariedPlusCommission): ");
t=stdIn.nextLine();
switch(t) {
case "Hourly":
return Hourly.load()
break;
// other cases
}
但是请注意,这不是好的做法,Employee
class 不应负责实例化其子class。此要求涉及使用 Employee
的代码。例如,不应该要求 Employee
class 了解其所有子 class。使用 Employee
的代码有此责任,因为只有该代码才能知道它想要支持哪些员工子类型。