1

this is my code:

System.out.println("--------------------------");
if (person instanceof Student) {
    Student studentPerson = (Student) person;
    System.out.println("GPA: " + studentPerson.getGpa());
    System.out.println("Major: " + studentPerson.getMajor());
    System.out.println("Year of Graduation: " + studentPerson.getYearOfGraduation());
} else if (person instanceof Employee) {
    Employee employeePerson = (Employee) person;
    System.out.println("Department: " + employeePerson.getDepartment());
    System.out.println("Job Title: " + employeePerson.getJobTitle());
    System.out.println("Year of Hire: " + employeePerson.getYearOfHire());

    if (employeePerson instanceof HourlyEmployee) {
        HourlyEmployee hourlyEmployeePerson = (HourlyEmployee) employeePerson;
        System.out.println("Hourly Rate: " + hourlyEmployeePerson.getHourlyRate());
        System.out.println("Hours Worked: " + hourlyEmployeePerson.getHoursWorked());
        System.out.println("Union Dues: " + hourlyEmployeePerson.getUnionDues());
    } else if (employeePerson instanceof SalariedEmployee) {
        SalariedEmployee salariedEmployeePerson = (SalariedEmployee) employeePerson;
        System.out.println("Annual Salary: " + salariedEmployeePerson.getAnnualSalary());
    } else if (employeePerson instanceof Nonprofessional) {
        Nonprofessional nonprofessionalPerson = (Nonprofessional) employeePerson;
        System.out.println("Hourly Rate: " + nonprofessionalPerson.getHourlyRate());
        System.out.println("Hours Worked: " + nonprofessionalPerson.getHoursWorked());
        System.out.println("Vacation Hours Earned: " + nonprofessionalPerson.getVacationHoursEarned());
    } else if (employeePerson instanceof Professional) {
        Professional professionalPerson = (Professional) employeePerson;
        System.out.println("Weekly Salary: $" + professional.calculateWeeklySalary());
        System.out.println("Health Care Contributions: $" + professional.computeHealthCareContributions());
        System.out.println("Vacation Days Earned: " + professional.computeVacationDaysEarned());
    } else if (employeePerson instanceof SalariedEmployee) {
        SalariedEmployee salariedEmployeePerson = (SalariedEmployee) employeePerson;
        System.out.println("Weekly Salary: $" + nonprofessional.calculateWeeklySalary());
        System.out.println("Health Care Contributions: $" + nonprofessional.computeHealthCareContributions());
        System.out.println("Vacation Days Earned: " + nonprofessional.computeVacationDaysEarned());
    }
}
System.out.println("--------------------------");

How would I change instanceof to polymorphism? I tried googling it but I am not sure how instanceof is not technically polymorphism. any help would be great as I am a first year university student and I don't know what I'm doing.

2
  • A good way to think about it is: with instanceof, you can relatively easily add a new method for different existing kinds of student/employee (you just create a new method and do instanceof checks within it for all possible cases), but it is hard to add new variants of of student/employee - because you have to change all the existing methods, assuming you want them to work with the new variant. 1/2 Jun 8, 2023 at 16:02
  • With dynamic polymorphism, you define an interface (usually a Java interface, but it doesn't actually have to be an interface, could be, for example, a set of strings that represent actions), and then any new variant (new derived class) has to support all the operations (normally enforced by the compiler, but could also be a bunch of if-statements). The problem is, here, it's easy to add new variants, but hard to support new operations (change the interface), cause you'd have to update all the variants (derived classes). 2/2 Jun 8, 2023 at 16:02

4 Answers 4

9

The defining criterion of polymorphic behaviour differences between classes is that the alternating behaviour is programmed within each class and not into any user of these classes.

In your case, this would mean that you have different Person subclasses, and each has an implementation of a printDetails() method that prints whatever is appropriate to objects of that type/class. The distinction between different classes is still made, but not as an explicit if and instanceof, but by the method resolution machinery that is built into the JVM.

3
  • 1
    For the sake of simplicity. this answer is fine, but I would like to add that a method like printDetails would not by my first choice. Maybe a method getDetails which returns a list of string or a list of key/value pairs, so the caller can decide for themselves what they are going to do with the returned values.
    – Doc Brown
    Jun 8, 2023 at 15:42
  • 3
    Agreed, absolutely the second thing I'd change about this code is to separate the responsibilities of getting and outputting class-specific data. But I have a strict policy of replying to beginners only on exactly one aspect. Jun 8, 2023 at 15:46
0

Querying for the actual type defeats the purpose of polymorphism.

Polymorphism is applicable when you can think of some common property or behavior among subclasses that would have different implementations for each subclass. You can read it quite literally: when you recognize different shapes of the same thing.

Like my face would (hopefully for you) look different from yours. We could both support a method ShowFace() and the results would be different but logically and semantically the behavior would be the same.

So, rather than writing "if this is Martin, show this face and if this is Raven, show that other face" you would write

SE_User.ShowFace()

and the applying implementation would kick in without the caller knowing or caring what particular user they are dealing with.

0

You have an object that might belong to one of say three classes, and you want different code to be executed depending on which class. There are two ways:

  1. In your code, use instanceof to determine which class you have, and execute different code depending on the class.
  2. In the superclass of your class, add a method that will have a different implementation for each of three subclasses (in some languages you can define the method in a protocol or interface, and the three classes need not be otherwise related). Then write three different implementations. The caller just calls this method.

Which one should you do? For example, your ui code might have five kinds of buttons. Each button class knows how to draw a button. Your caller has not the slightest interest in knowing what the button looks like. Use polymorphism, with different code in each class. Another example, you write some different explanatory text depending on the class. Two classes don’t want to make this text part of their interface, so you pull the decision into your code. (This is rare).

Another way is making objects configurable. You set a property to change the behaviour. Or you mix things: you have a method that does most of the work, different per class, and pass info about differences to the method.

-2

There is a formally defined refactoring called Replace Conditional with Polymorphism. It is generally applied to sibling branch logic: else if or case. The method your breaking up would be implemented in each type/class and the choice to follow that branch would have been made when that type/class was configured to handle this call.

However, you have a mix of sibling and child if ... if. With that it will require either subtypes or composition to nest the same behavior under the call.

For example:

Person p = new HourlyEmployee(new Employee());

this would build a person that you could call with:

p.report();

and it would display things like Department and Hourly Rate.

This is polymorphism by composition. It shows up in many patterns. Give the Decorator Pattern a read. It's a good place to start.

5
  • In case it isn't obvious from this answer, if each person class had an appropriate report() function, then that entire if ... else if ... lump of code in the OP's question could be replaced by the one line "person.report();"
    – Simon B
    Jun 8, 2023 at 14:32
  • @SimonB in the calling code yes. But the println() code has gotta go somewhere. One could hide all the if logic under a report() function in one file and the calling code would look the same. The point is to let the code for different types live in different files so when they're unchanged they remain untouched. Jun 8, 2023 at 14:36
  • 1
    Decorator pattern intent makes it inappropriate here. Decorator is encapsulating - hiding - a design flaw. Decorator is not a substitute for polymorphism, which is a feature of inheritance. If ToString(), let's say, is the dynamic operation the misapplication is more apparent. Decorator customizes same class objects but here the output are core attributes fundamental to the definition of different classes.
    – radarbob
    Jun 8, 2023 at 23:02
  • ”The decorator pattern can be used to extend (decorate) the functionality of a certain object” because wikipedia said so : P Jun 8, 2023 at 23:28
  • "This is my weapon, this is my gun. This is for fighting, this is for fun." - USMC basic training => I.E. It is important to use the proper tool for the job.
    – radarbob
    Jun 26, 2023 at 20:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.