Assignment of Subclass and Superclass Objects

Consider our earlier Employees/Managers example.

Because class Manager is a kind of Employee, we can refer to it using the type Employee (staff[2] is of type Employee):

staff[2] = new Manager("Mother Theresa",
                       120000,
                       new Date(89, 3, 5),
                       "Demi Moore");

but we can’t call Manager-specific methods through that reference:

String sec = staff[2].getSecretaryName(); // Error

Java gives a compilation error:

Error: Method getSecretaryName() not found in Employees.Employee

If we know that it really is a Manager, then we can cast it:

String sec = ((Manager)staff[2]).getSecretaryName();

but if it really isn’t a Manager,

String sec = ((Manager)staff[0]).getSecretaryName();

then Java throws an exception at run time:

java.lang.ClassCastException

It’s best to try to restrict this kind of casting only to within code that is hidden from the outside world!

In general, you can assign a superclass object to a subclass object:

Employee colleague = new Manager();

but not the other way around:

Manager colleague = new Employee(); // Error

In this case, Java gives a compile-time error:

Error: Incompatible type for vardeclaration. 
    Explicit cast needed to convert Employees.Employee 
    to Employees.Manager

Why?

Method Parameters

Subclass and Superclass Objects as Method Parameters

It is possible (and actually a very common practice) to declare a method with one or more parameters of superclass types, and then actually pass subclass objects.

For example, imagine that we had an expanded class hierarchy:

We need to add some new classes to represent this new hierarchy:

  • Secretary
  • Executive
  • ExecutiveSecretary
  • Programmer

and we also will make some modifications to the existing Manager class.

Secretary

Here’s class Secretary:

package company;

import java.util.Date;

public class Secretary extends Employee
{
    public Secretary(String n, double s, Date d, int ts)
    {
        super(n, s, d);
    }
    
    public int getTypingSpeed()
    {
        return m_typingSpeed;
    }
    
    public void setTypingSpeed(int ts)
    {
        m_typingSpeed = ts;
    }
    
    //////////// Data //////////////////
    private int	m_typingSpeed;
}

ExecutiveSecretary

Here’s class ExecutiveSecretary:

package company;

import java.util.Date;

public class ExecutiveSecretary extends Secretary
{
    public ExecutiveSecretary(String n, double s, 
                              Date d, int ts)
    {
        super(n, s, d, ts);
    }

    // Other attributes of an Executive Secretary...
}

Manager

Now, let’s make some changes to class Manager so it can refer to the Secretary object, rather than just use the name of secretary:

package company;

import java.util.Date;

public class Manager extends Employee
{
    public Manager(String n, double s, Date d, Secretary sec)
    {
        super(n, s, d);
        m_secretary = sec;
    }
    
    public void raiseSalary(double byPercent)
    {
        // Add 1/2% bonus for every year of service
        Date today = new Date();
        double bonus =
                0.5 * (today.getYear() + 1900 - getHireYear());
        super.raiseSalary(byPercent + bonus);
    }
    
    public Secretary getSecretary()
    {
        return m_secretary;
    }
    
    public void setSecretary(Secretary sec)
    {
        m_secretary = sec;
    }
    
    //////////// Data //////////////////
    private Secretary	m_secretary;
}

Executive

Here’s class Executive:

package company;

import java.util.Date;

public class Executive extends Manager
{
    public Executive(String n, double s, Date d, 
                     ExecutiveSecretary sec)
    {
        super(n, s, d, sec);
    }
    
    public void raiseSalary(double byPercent)
    {   
        // Add 20% options bonus 
        double options_bonus = 20.0;
        super.raiseSalary(byPercent + options_bonus);
    }
}

Note the extra bonus in raiseSalary

Programmer

And finally, here’s class Programmer:

package company;

import java.util.Date;

public class Programmer extends Employee
{
    public Programmer(String n, double s, Date d,
                      String[] langs)
    {
        super(n, s, d);
        m_languages = langs;
    }
    
    public String[] getLanguages()
    {
        return m_languages;
    }
    
    public void setLanguages(String[] langs)
    {
        m_languages = langs;
    }
    
    //////////// Data //////////////////
    private String[]	m_languages; // Programming languages
}

Test Program

Now, here’s a test program to use the new features:

package company;

import java.util.Date;

public class CompanyTest
{
    public static void main(String[] args)
    {
        Employee[] staff = new Employee[6];

        staff[0] = new Employee("Charlie Chaplin", 34000,
                                new Date(78, 7, 9));
        staff[1] = new Secretary("Demi Moore", 17000,
                                new Date(95, 8, 16), 15);
        staff[2] = new ExecutiveSecretary("Florence Nightingale",
                                50000, new Date(71, 4, 23), 150);
        staff[3] = new Manager("Mother Theresa", 0,
                                new Date(89, 3, 5), 
                                (Secretary)staff[1]);
        staff[4] = new Executive("Bill Gates", 42000000, 
                                new Date(90, 1, 1),
                                (ExecutiveSecretary)staff[2]);
        String[] languages = {"Java", "C++", "C" };
        staff[5] = new Programmer("Bryan Higgs", 250000,
                                new Date(76, 4, 12),
                                languages);

        for (int i = 0; i < staff.length; i++)
            staff[i].raiseSalary(5);     // by 5 percent

        for (int i = 0; i < staff.length; i++)
            staff[i].print();

        Secretary sec = ((Manager)staff[3]).getSecretary();
        System.out.println(staff[3].getName() + "'s secretary: " 
                            + sec.getName());
        sec = ((Executive)staff[4]).getSecretary();
        System.out.println(staff[4].getName() + "'s secretary: "
                            + sec.getName());
        Programmer prog = (Programmer)staff[5];                    
        System.out.println(prog.getName()
                            + " knows the following languages:");
        String[] langs = prog.getLanguages();
        for (int lang = 0; lang < langs.length; lang++)
        {
            if (lang != 0)
                System.out.print(",");
            System.out.print(langs[lang]);
        }
        System.out.println();
    }
}

It produces the following output:

Charlie Chaplin 35700.0 1978
Demi Moore 17850.0 1995
Florence Nightingale 52500.0 1971
Mother Theresa 0.0 1989
Bill Gates 5.565E7 1990
Bryan Higgs 262500.0 1976
Mother Theresa's secretary: Demi Moore
Bill Gates's secretary: Florence Nightingale
Bryan Higgs knows the following languages:
Java,C++,C