Calling child methods while using polymorphism in an arraylist - java

I have a small project that I'm working with inheritance and polymorphism. I have an ArrayList of type Employee that contains both Hourly and Salary employee objects. I would like to be able to use a for loop to call a calcPay function in the Hourly class provided the object in the ArrayList of type Employee is an Hourly employee. The line
System.out.println("Wage: " e.calcPay());
Gives the error The method calcPay() is undefined for type employee. How do you downcast the object? I've looked in a lot of forums and I couldn't find an option that would allow me to do it inline or without writing an abstract method that I'd have to include in all of the child classes of Employee. Any insight would be much appreciated.
public class Driver {
public static void main(String[] args) {
ArrayList<Employee> list = new ArrayList<Employee>();
Employee emp1 = new Hourly("Hourly Emp", "123 E Center", "555-555-5555", 00001, "123-45-6789", 12.75);
Employee emp2 = new Salary("Salary Emp", "123 E Center", "555-555-5555", 00001, "123-45-6789");
list.add(emp1);
list.add(emp2);
for(Employee e : list){
if(e instanceof Hourly)
{
System.out.println("Wage: " e.calcPay());
}
}
}
public abstract class Employee {
private String name, address, phone, ssn;
private int empNo;
Employee(String name, String address, String phone, int empNo, String ssn)
{
this.name = name;
this.address = address;
this.phone = phone;
this.empNo = empNo;
this.ssn = ssn;
}
}
public class Hourly extends Employee {
private double wage;
Hourly(String name, String address, String phone, int empNo, String ssn, double wage)
{
super(name, address, phone, empNo, ssn);
this.wage = wage;
}
public double calcPay(double hours)
{
return wage * hours;
}
}

Even though you are making sure e is of type Hourly, you still need to cast it and use Hourly type to call calcPay() because e is of type Employee and Employee is not aware of any calcPay() method because you have defined calcPay() as only Hourly class method.
if(e instanceof Hourly)
{
Hourly hourly = (Hourly)e;
System.out.println("Wage: " hourly.calcPay());
}
If you want calcPay() accessible for all Employee instances, you need to define calcPay() as abstract method in Employee class, then you can avoid casting.
Updated:
if(e instanceof Hourly)
{
System.out.println("Wage: " ((Hourly)e).calcPay());
}

If calcPay is supported for all Employees, then it should be an abstract method in Employee, which will let you call it without having to downcast at all.

Related

Accessing private instance fields of parent class from subclass.. but it works?

I have a parent class that has 2 private instance fields but my child class which has no instance fields 'magically' creates 2 instance fields.
public class Parent
{
private String firstName;
public String lastName;
private int age;
public Parent()
{
System.out.println("No-Parameter Constructor");
}
public Parent(String firstName, String lastName, int age)
{
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public String toString()
{
return "firstName: " + firstName + " lastName: " + lastName + " age: " + age;
}
public String getFN()
{
return firstName;
}
}
public class Student extends Parent
{
public Student(String firstName, String lastName, int age)
{
super(firstName, lastName, age);
}
public static void main(String[] args)
{
Parent p = new Parent("Logi", "Tech", 42);
Student s = new Student("Logi", "Camera", 21);
System.out.println(p);
System.out.println(s);
System.out.println(p);
System.out.println(p.getFN());
}
}
Output:
firstName: Logi lastName: Tech age: 42
firstName: LogiStudent lastName: Camera age: 21
firstName: Logi lastName: Tech age: 42
LogiStudent
You are not accessing private fields from the Student class. Just look at your code - nowhere in the body of class Student extends Parent {} do you refer to those fields in any way.
class Student extends Parent is java-ese for: "Let's define this new concept called Student. Begin by taking absolutely every single last thing Parent has, and then bolt, on top of all that, a few more things".
In other words, if Parent has the field 'age, then so does Student.
accessibility is almost entirely unrelated to this notion; accessibility (private) is about which code (NOT which instance!!) is allowed to directly interact with things. Given that the age field is private, whilst every instance of Student has that field, the code located in Student.java cannot touch that field directly. It is of course free to invoke a method that its superclass does allow access to (such as the toString method which is public) and then observe as IT touches those fields. That's not 'direct access', that's indirect, and that is fine.
Similarly, Student can invoke getFN() anywhere it wants, and thus get the first name. It cannot, however, set the firstname, unless Parent decides to add a void setFirstName(String fn) { this.firstName = fn; } method, of course.

How to set salary for object before adding it arraylist

Im reading data from a text file
which includes information about employees details
as the following:
H ,name ,socialNumber,hours,rate
S,name,social number,salary
and add them to tow lists.
If they are hourly employee:
H.add(new Hourly(name ,number,hour,rate);
Else if they were salaried:
S.add(new salaried(name,number);
The question is: how to add the salary for the employee before adding the object to the list?
hourly = rate*hours
Salaried = salary
I have attribute salary
and mutator method which sets double salary
I also set the salary after adding the object to the list,
but the took the last salary form the text
The first 1500 the second 2000
If you want to set the Salary before adding it to the List, you can define the new Entry before, change the Salary and then adding it:
Salaried s = Salaried(name,number);
s.setSalary(computedSalary);
S.add(s);
I hope that help you,
Regards
You may consider the builder pattern, which offers a flexible way of constructing objects:
public class Salaried {
String name;
String socialNumber;
Double salary;
...
public static class Builder {
String name;
String socialNumber;
Double salary;
public Builder(String name, String socialNumber) {
this.name = name;
this.socialNumber = socialNumber;
}
public Builder salary(Double salary) {
this.salary = salary;
return this;
}
public Salaried build() {
Salaried salaried = new Salaried(name, socialNumber);
salaried.setSalary(salary);
return salaried;
}
}
}
S.add(new Salaried.Builder("bob","12345678").salary(40000).build());

I need to create a map from an farm object list using the salary from Emploee class

This is the code I wrote so far for the other things I need to do. The main problem is that even with so much info I can't understand how to do it.
Create a map from the farm list which has like key the salary and like value the list of employee that has that salary. Display the map content, and for each employee display the farm in which is working
public class Employee implements Comparable<Employee> {
private String name;
private Integer salary;
public Employee (String name , Integer salary) {
this.name = name;
this.salary = salary;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSalary(Integer salary) {
this.salary = salary;
}
public Integer getSalary() {
return salary;
}
public String toString() {
return name + " " + salary;
}
public int compareTo(Employee emp) {
return this.salary.compareTo(emp.getSalary());
}
}
Farm class
public class Farm {
private String name;
private Integer surface;
List<Employee> emp = new ArrayList<Employee>();
public Farm(String name , Integer surface) {
this.name = name;
this.surface = surface;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSurface(Integer surface) {
this.surface = surface;
}
public int getSurface () {
return surface;
}
public String toString() {
return name + " " + surface;
}
public void makeList(String ename , Integer esalary) {
this.emp.add(new Employee(ename,esalary));
}
public void getList() {
for(Employee el : emp)
System.out.println(el);
}
public Employee getMostPaidEmployee() {
return Collections.max(emp);
}
}
And my main one
public static void main(String args[])
{
List <Farm> FarmList = new ArrayList<Farm>();
Farm farm1 = new Farm("Tiguana" , 700);
farm1.makeList("Mihai", 30000);
farm1.makeList("Vladimir", 4000);
farm1.makeList("Tusnic", 3000);
farm1.getList();
System.out.println(farm1.getMostPaidEmployee());
Farm farm2 = new Farm("Tipirei" , 800);
farm2.makeList("Mihai", 30000);
farm2.makeList("Mihail", 40000);
farm2.makeList("Armando", 50000);
farm2.makeList("ASihai", 60000);
System.out.println(farm2.getMostPaidEmployee());
FarmList.add(farm2);
FarmList.add(farm1);
}
Map< Integer , List< Employee > >
Sounds like you want to build a Map< Integer , List< Employee > >. The key, of type Integer (object, not primitive int), is the salary. The value is a List of employees with that particular salary.
So you need to instantiate such a Map, probably a HashMap, or perhaps a SortedMap such as TreeMap. Then as you loop the employees, you see if their salary has already been added as a key to the map. If not, add the salary as a key, and create an empty List object as the value. Add that particular employee to the new list. If the salary is already present, retrieve the list, add the employee.
To report by farm, you need to find which farm hired that employee. You will loop the keys of the map, for each key retrieve its list of employees, and then loop those employees. For each employee, loop all the farms, and retrieve each farm’s list of employees, and see if the target employee is in that list. If so, you know the farm of the employee in the list on the map.
One flaw in your code is defining a compareTo on Employee by salary. Intuitively we can tell that does not smell right. You should instead have an identifier on each employee, like most any company assigns an “employee id” to each person hired. For the sake of your exercise, I would just use a UUID as the id. Add a member field of type UUID to your Employee class. Define compareTo using that object.
As this is obviously homework, I think I have said enough. You should be able to figure this out following my prose. You can also search Stack Overflow for many many examples of maps with a list as the value, and other such issues.
In real work, we would likely be concerned with concurrency issues. But I assume that was not intended as part of your school assignment.
See also the coding-style tips I posted as Comments on the Question.
This is how you gonna do it :
Map<Integer, List<Employee>> map = new HashMap<>();
for(Farm f : FarmList){
for(Employee e : f.emp){
if(!map.containsKey(e.salary)){
map.put(e.salary, new ArrayList<>());
}
map.get(e.salary).add(e);
}
}
Be sure to add the field of FarmName to your employee and override toString() method in Employee class so you can display what's asked.

How do I implement these super class methods?

What I'm supposed to do:
write a java program to show the inheritance concept with an Employee being the super class and the Manager being the sub-class. Follow the following class structure: - Employee class
Variables:
Employee Number
Employee Name
Employee Salary
Constructor – Use this to initialize all the variables above Functions
Display() – This displays all the 3 variable values.
setSalary() – This sets the salary variable.
getSalary() – This gets the salary variable.
Heres what I have so far
public class Employee {
private int employeeNumber;
private String employeeName;
private double employeeSalary;
public Employee(int employeeNumber, String employeeName, double employeeSalary) {
this.employeeNumber = employeeNumber;
this.employeeName = employeeName;
this.employeeSalary = employeeSalary;
}
}
My question is how do I implement those three methods?
Are they just standard getters and setters?
I'm not familiar with the display function, if anyone can help with that
thanks!
You are really close. You need to create the manager Class and extend the Employee Class. But first let's add the described method for setting the salary and displaying all the fields!
Employee Class: The display() method concatenates the fields together separating them by line.
public class Employee {
private int employeeNumber;
private String employeeName;
private double employeeSalary;
public Employee(int employeeNumber, String employeeName, double employeeSalary){
this.employeeNumber=employeeNumber;
this.employeeName=employeeName;
this.employeeSalary=employeeSalary;
}
public void display(){
System.out.println("Employee Number: "+ employeeNumber +"\n"
+ "Employee Name: " + employeeName + "\n"
+ "Employee Salary: " + employeeSalary);
}
public double getEmployeeSalary() {
return employeeSalary;
}
public void setEmployeeSalary(double employeeSalary) {
this.employeeSalary = employeeSalary;
}
}
Manager Class: From general knowledge I would assume that a Manager could have multiple employees also.
So in this class you'd have specific methods for the Manager, such as adding a new Employee, or displaying or the Employees who work for a given Manager.
public class Manager extends Employee {
List<Employee> subordinates;
public Manager(int employeeNumber, String employeeName, double employeeSalary) {
super(employeeNumber, employeeName, employeeSalary);
subordinates = new ArrayList<>();
}
public void displayEmployees(){
for(Employee employee: subordinates){
employee.display();
// just print an empty line - so its prettier
System.out.println();
}
}
public void addNewEmployee(Employee employee){
subordinates.add(employee);
}
public List<Employee> getSubordinates() {
return subordinates;
}
public void setSubordinates(List<Employee> subordinates) {
this.subordinates = subordinates;
}
}
Testing: note that a Manager inherits all the methods of the Employee class, which is why within the Manager class there was no need to override the methods, but of course that can be done to add new functionality.
public class Main {
public static void main(String[] args) {
Manager manager = new Manager(11111, "Elon Musk", 42344);
manager.display();
// lets make some employees who work for the above manager
Employee employeeOne = new Employee(324, "Bob Den", 3522);
Employee employeeTwo = new Employee(44, "Tim Pipe", 4234 );
Employee employeeThree = new Employee(42, "Asif Blar", 4321);
// lets add the new employees to the managers list of employees ( this can further be refactored )
manager.addNewEmployee(employeeOne);
manager.addNewEmployee(employeeTwo);
manager.addNewEmployee(employeeThree);
// lets display all the employees who work for the manager
manager.displayEmployees();
// lets give the manager a 10 % raise
double employeeSalary = manager.getEmployeeSalary();
manager.setEmployeeSalary(employeeSalary +(employeeSalary /10));
// lets print out the managers hefty new salary
manager.display();
}
}

Sort by age method, and list in class

I'm trying to refresh my java skills here. I am working on a simple java assignment. Below are the first two instructions.
Create an Employee class with following attributes / variables:
name
age
department
Create a class called Department which will contain a list of employees.
a) Department class will have a method which will return its employees ordered by age.
b) The value of department can be only one of the following values:
“Accounting”
“Marketing”
“Human Resources”
“Information Systems”
I'm having a little trouble with step 2. I need help figuring out how to add a list of employees like it says, and how to write the method which will return by sorting the employees ordered by age.
I would just like for someone to explain how to do this. Thanks.
So far I have this.
Employee Class:
package simpleJavaAssignment;
public class Employee {
String name;
int age;
Department department;
Employee(String n, int a, Department d)
{
this.name = n;
this.age = a;
this.department = d;
}
int gAge(){
return age;
}
}
Department Class:
package simpleJavaAssignment;
import java.util.*;
public enum Department {
ACCOUNTING("Accounting"), MARKETING("Marketing"), HUMAN_RESOURCES(
"Human Resources"), INFORMATION_SYSTEMS("Information Systems");
private String deptName;
Department(String deptName) {
this.deptName = deptName;
}
#Override
public String toString() {
return this.deptName;
}
}
You have the beginnings of a solution but you are a ways off yet.
Your Department class (should be a class and not an enum), should contain a collection of Employee objects. There should also be a collection of departments at the top level in your program.
As to sorting, you should look at the Comparator interface. You implement a custom subclass of Comparator that allows the builtin collection sorting algorithms to compare Employee instances such that the desired order is achieved.
public class EmployeeAgeComparator implements Comparator<Employee>
{
public int compare(Employee e)
{
return (this.age < e.age)
? -1
: (this.age > e.age)
? +1
: 0;
}
}
This fulfills the Comparator contract by returning -1 if this Employee is younger than e, zero if they are the same age, and +1 if this Employee is older.
You can set the list of employees be ordered by age when you add an employee to the list.
Then when you want to get the list, you just return it.
You should not contain a Department member in Employee class, Conversely, Department class should contain a list of Employee.
package simpleJavaAssignment;
import java.util.*;
public class Department {
private String deptName;
private ArrayList<Employee> employees;
Department(String deptName) {
this.deptName = deptName;
this.employees = new ArrayList<Employee>();
}
public String toString() {
return this.deptName;
}
public void addEmployee(Employee a){
if( employees.isEmpty())
employees.add(a);
else
{
int i;
for( i = 0; i < employees.size(); ++i ){
if( employees.get(i).gAge() > a.gAge() ){
employees.add(i, a);
break;
}
}
if( i == employees.size() )
employees.add(a);
}
}
public ArrayList<Employee> getEmployees(){
return employees;
}
}

Categories