简体   繁体   English

在抽象类中返回对象的解决方法

[英]Workaround for returning object in abstract class

I'm working on a payroll program for school and have a Payroll driver, Employee class, Hourly class (which extends Employee), Salaried class(extends Employee), and SalariedPlusCommission class (extends Salaried). 我正在为学校制定薪资计划,并且有薪资驱动程序,雇员班,每小时班(扩展雇员), Salaried阶层(扩展雇员)和SalariedPlusCommission类别(扩展Salaried)。 The code below is the Employee object and the load() method from Employee (also a load() method in each subclass). 下面的代码是Employee对象和Employee中的load()方法(也是每个子类中的load()方法)。 I have to have an abstract method getEarnings() so the entire Employee class is abstract. 我必须有一个抽象方法getEarnings()所以整个Employee类都是抽象的。 I'm getting an error that says "Employee is abstract; cannot be instantiated". 我收到一个错误消息:“雇员是抽象的;无法实例化”。 I understand why I'm getting the error but I don't know how to get the info into my Employee object. 我知道为什么会收到错误,但不知道如何将信息放入我的Employee对象中。

    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);
        }

If it helps here is the Hourly object and load() method from Hourly: 如果有帮助,可以使用Hourly中的Hourly对象和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);
}

As soon as you add an abstract method to a class then you can no longer instantiate it. 将抽象方法添加到类后,就无法再实例化它。 In your scheme, you can instantiate Hourly, Salaried, and SalariedPlusCommission if they provide an implementation for getEarnings() and any other abstract methods declared by Employee. 在您的方案中,如果它们提供了getEarnings()和Employee声明的任何其他抽象方法的实现,则可以实例化Hourly,Salaried和SalariedPlusCommission。

A common intent for a class hierarchy like this is to use Employee to hold behaviors (code) common to all your sub-classes. 这样的类层次结构的共同意图是使用Employee来保存所有子类共有的行为(代码)。 You extend it and never instantiate it directly. 您扩展它,并且永远不要直接实例化它。

If you do need to instantiate Employee, then you must provide an implementation of getEarnings() and probably ALSO override the implementation in each subclass. 如果确实需要实例化Employee,则必须提供getEarnings()的实现,并且可能还会在每个子类中重写该实现。 The base implementation can return a null or even throw an exception if you like. 如果需要,基本实现可以返回null或引发异常。 Having a NOOP base implementation strikes me as a potential "bad code smell", but I don't know what else you are trying to accomplish. 具有NOOP基本实现会让我感到潜在的“不良代码味道”,但我不知道您还想实现什么。

You could also create an IEarn interface with just that method and have each subclass implement it (but not Employee). 您也可以仅使用该方法创建IEarn接口,并让每个子类实现它(但不能使用Employee)。 The problem here is that you won't be able to declare all your entities as the base class for treating them polymorphically with regards to earning. 这里的问题是,您将无法将所有实体都声明为基类,从而无法在收入方面对它们进行多态处理。 You won't be able to do: 您将无法执行以下操作:

Employee foo = new Hourly();
Employee baz = new Salaried();
baz.getEarnings();
foo.getEarnings();

You'd have to do: 您必须执行以下操作:

IEarn foo = new Hourly();
IEarn baz = new Salaried();
baz.getEarnings();
foo.getEarnings();

But the typical thing to do here would be to design your class hierarchy so that Employee was useful as an abstract class and never instantiated directly. 但是,这里要做的典型事情是设计您的类层次结构,以便Employee作为抽象类很有用,并且从未直接实例化。

Employee is an abstract class, which means it does not implement all of its methods. Employee是一个抽象类,这意味着它没有实现其所有方法。 It is up to subclasses to implement those methods with the proper behavior. 由子类来实现具有适当行为的那些方法。 Therefore, it does not make sense to load an Employee , while it does make sense to load an Hourly , since it implements all methods. 因此,加载Employee并没有意义,而加载Hourly则有意义,因为它实现了所有方法。

You shouldn't be trying to instantiate an employee. 您不应该尝试实例化员工。 Instead, remove the load() method from the Employee class and keep only the Hourly , Salaried and SalariedPlusCommission load() methods. 而是从Employee类中删除load()方法,并仅保留HourlySalariedSalariedPlusCommission load()方法。

If you need to create a load() method for Employee , then ask the user what kind of employee he/she wants: 如果您需要为Employee创建load()方法,请询问用户他/她想要什么样的雇员:

System.out.println("Type (Hourly, Salaried or SalariedPlusCommission): ");
t=stdIn.nextLine();
switch(t) {
   case "Hourly":
       return Hourly.load()
       break;
    // other cases
}

Note, however, that this isn't good practice and the Employee class shouldn't be responsible for instantiating its subclasses. 但是请注意,这不是一个好习惯,并且Employee类不应该负责实例化其子类。 This requirement comes to the code that is using Employee . 此要求涉及使用Employee的代码。 For instance, the Employee class should not be required to know about all of its subclass. 例如,不要求Employee类了解其所有子类。 This onus comes to the code that uses Employee , as only that code can know which employee subtypes it wants to support. 这是使用Employee的代码的责任,因为只有该代码才能知道它要支持的员工子类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM