在Java中创建一个超类类型的数组中的子类对象

3

我试图涵盖OOP的内容,但是我卡在这里了。我在Company类中,employees[0].setBonus(50)部分收到错误。除了在Employee类中定义Bonus方法之外,是否有其他解决方法?还是有没有办法将所有对象保存在一个数组中?我定义了奖金方法,但还有另一件事,我必须在Empoyee类的getBonus方法中返回什么?


   public class Company
    {
    private static Employee[] employees;
    public Company()
    {
    employees= new Employee[]{new Manager("Sapo",10000),new Employee("James",5000),new Employee("Jessie",5001)};
    }
    public static void main(String[] args)
    {
        Company company= new Company();
        employees[0].setBonus(50);
        System.out.println(employees[0].getBonus());    
    }
    }

public class Employee extends Person
{
 int salary;
public Employee(String name,int salary) {
    super(name);
    setSalary(salary);
    // TODO Auto-generated constructor stub
}
public void setSalary(int salary)
{
    this.salary= salary;
}
public int getSalary()
{
    return salary;
}
}

    public class Manager extends Employee
{
private int bonus;

public Manager(String name, int salary) {
    super(name, maas);
}
public void setBonus(int bns)
{
    bonus=bns;
}

public int getBonus()
{
    return bonus;
}
public int getSalary()
{
    return salary+bonus;
}
}

我感到困惑。

可能是 Calling a subclass method from superclass 的重复问题。 - shmosel
3个回答

3
如果你真的想这样做,你可以把employee[0]当作manager来处理,但是你必须知道这不是一个好的解决方案。例如:
    Company company= new Company();
    Manager manager = Manager.class.cast(employees[0]);
    manager.setBonus(50);
    System.out.println(manager.getBonus());

2
或者有没有办法将所有对象保存在一个数组中?
你可以这样做,但这会迫使你编写以下代码:
if ( employees[0] instanceof Manager){
   ((Manager) employees[0]).setBonus(50);
}

这并不是一个好的实践。

从功能上来看,如果奖金是仅属于Manager实例拥有的属性,则Employee实例不应尝试设置或获取它。

当你执行以下操作时:

 employees[0].setBonus(50);

编译器不知道具体实例,它只看到 Employee。在这个非常简单的代码中,我们可以直接看到第一个员工是经理,但在实际应用中,数组可能会多次修改。试图记住哪些索引是经理是容易出错的。如果需要在一个或多个经理上调用特定的经理方法,则应确信知道哪些变量是经理。因此,将他们声明为经理似乎更自然。
为解决您的问题,两个数组似乎更有趣:一个是员工数组,另一个是经理数组:
private static Employee[] employees;

private static Manager[] managers;

现在你可以做到:

public Company()
{
   employees= new Employee[]{new Employee("James",5000),new Employee("Jessie",5001)};
   managers= new Employee[]{new Manager("Sapo",10000)};
}

 public static void main(String[] args){
        Company company= new Company();
        managers[0].setBonus(50);
        System.out.println(managers[0].getBonus());    
    }

1
你的抽象化错误了。你看,编译器只有在编译时可用的信息。
你有一个 Employee 对象的数组。在运行时,你的代码将 Manager 对象放入该数组中也无关紧要!编译器不知道那一点。他只知道有一个雇员。
而且 Employee 类没有方法 setBonus()。因此你不能调用该方法!
一个可能的解决方案是使奖金成为 Manager 构造函数的参数;整个代码可以如下所示:
public class Manager extends Employee {
  private final int bonus;

  public Manager(String name, int salary, int bonus) {
    super(name, salary);
    this.bonus = bonus;
  }

  @Override
  int getSalary() {
    return super.getSalary() + bonus;
  }

注意:

  • 应该避免使用超类的字段;它们是那个类的私有实现细节。子类不应该关心它们。相反,您可以从超类调用方法。
  • 另一方面,您应该努力使您的字段最终。这会让很多事情变得更加容易。
  • 覆盖方法时...请使用@ Override注释!

最后:构造函数是创建您的“测试数据”的不好的地方。换句话说:您的主要方法是创建员工数组的地方;然后您只需将其传递到您的公司构造函数中。您希望清楚地将“真正的业务逻辑”与主要存在于测试“业务逻辑”的东西分开。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接