nerdicsapo
nerdicsapo

Reputation: 427

Creating subclass object in an array which type of superclass in java

I'm trying to cover OOP stuffs but I stuck here. I get error in Company class, employees[0].setBonus(50) part. Isn't there any other way to solve it except defining Bonus methods in Employee class? Or is there anyway to keep all objects in one array? I defined bonus methods but there was another thing, what I have to return in Empoyee class' getBonus method?


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

I'm confused.

Upvotes: 3

Views: 1765

Answers (3)

MatWdo
MatWdo

Reputation: 1740

If you really want do it this way, you can cast employee[0] as manager, but You must know is not nice solution. E.g:

    Company company= new Company();
    Manager manager = Manager.class.cast(employees[0]);
    manager.setBonus(50);
    System.out.println(manager.getBonus());

Upvotes: 3

davidxxx
davidxxx

Reputation: 131346

Or is there anyway to keep all objects in one array?

You could but it would force you to write :

if ( employees[0] instanceof Manager){
   ((Manager) employees[0]).setBonus(50);
}

which is not a good practice.

Functionally, if a bonus is a property which owns only the Manager instances, an Employee instance should not try to set or get it.

When you do :

 employees[0].setBonus(50);

the compiler doesn't know the concrete instance. It sees only Employee. In this very simple code, we see straight that the first employee is a manager but in a real application the array may be modified multiple times. Trying to remember at which indexes are the managers is error prone. If you need to call a manager specific method on a or several managers you should be sure about knowing which variables are managers. So declaring them as manager seems the more natural way.

To solve your problem, two arrays seems more interesting : one for employees and another for managers :

private static Employee[] employees;

private static Manager[] managers;

Now you can do :

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

Upvotes: 2

GhostCat
GhostCat

Reputation: 140427

Your abstraction is wrong. You see, the compiler only has that information that is available at compile time.

You have an array of Employee objects there. It doesn't matter that your code at run time will put a Manager object into that array! The compiler doesn't know that. He only knows that there is an Employee.

And the Employee class has no method setBonus(). Thus you can't call that method!

One possible solution would be for example to make the bonus a parameter to the constructor of Manager; the whole think could look like this:

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

Notes:

  • You should avoid to use fields of your super class; those are private implementation details of that class. Child classes should not care about them. Instead, you could call the method from the super class.
  • On the other hand, you should strive for making your fields final. That makes a lot of things much easier.
  • When overriding methods ... use the @Override annotation!

Finally: a constructor is a bad place to create your "test data". In other words: your main method is to place to create that array of employees; and then you just pass that into your Company constructor. You want to clearly separate your "real business logic" from that stuff that mainly exists to test that "business logic".

Upvotes: 1

Related Questions