I have two java class:
class Employee{
private name;
private annualSalary;
public Employee(String name, double annualSalary){
}
}
and
class HourlyEmployee extends Employee{
public HourlyEmployee(String name, double annualSalary, double hourlySalary){
super(salary, annualSalary);
this.hourly = hourlySalary;
}
}
Is there a way I can get rid of the annualSalary from the inherited class understanding that the annualSalary = hourlySalary * 200? by default when the HourlyEmployee class is created. The value for annualSalary will be empty or set to hourlySalary * 200.
Remove annualSalary and pass hourlySalary * 200 to super-class constructor.
public class HourlyEmployee extends Employee {
private double hourlySalary;
public HourlyEmployee(String name, double hourlySalary) {
super(name, hourlySalary * 200);
this.hourlySalary = hourlySalary;
}
}
Your class structure is wrong because not all employees get an annual salary. Get rid of annualSalary from Employee and create two subclasses: HourlyEmployee that has an hourly salary and a SalariedEmployee that has an annual salary. If needed, introduce an abstract method getAnnualSalary in Employee (and make Employee abstract) and implement it differently in the two subclasses.
abstract class Employee {
private String name;
public Employee(String name) { ... }
public abstract double getAnnualSalary();
}
class SalariedEmployee extends Employee {
private double annualSalary;
public SalariedEmployee(String name, double annualSalary) {
super(name);
this.annualSalary = annualSalary;
}
#Override
public double getAnnualSalary() { return annualSalary; }
}
class HourlyEmployee extends Employee {
private double hourlySalary;
public HourlyEmployee(String name, double hourlySalary) {
super(name);
this.hourlySalary = hourlySalary;
}
#Override
public double getAnnualSalary() { return 200 * hourlySalary; }
}
You might also want to explore using interfaces to define employee behavior, rather than using a base class.
Needing to omit parent class attributes is a code smell called refused bequest. If an hourly employee does not have a yearly salary, the class that represents an hourly employee should not inherit from the class that represents a salaried employee.
The solution is extracting the parts they have in common to a separate class, or several different classes, depending on the case. In your current contrived example there's nothing the two classes have in common, and I see no point in using inheritance to begin with.
Related
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();
}
}
I want to fill values in my arraylist of abstract class type.Below is my code
public abstract class Account {
private int accountId;
private int customerId;
private double balance;
public Account(int accountId, int customerId, double balance) {
this.accountId = accountId;
this.customerId = customerId;
this.balance = balance;
}
public abstract double deposit(double sum);
public abstract double withdraw(double sum);
}
Above is my abstract class.
Now I have another class bank in which i want to define and declare an arraylist in which i can fill my values .
I declared arraylist as
ArrayList<Account> al=new ArrayList<>();
Now i want to pass values to this arraylist for further use but i couldnot as we cannot instantiate abstract class.I tried this code to fill values in class with main method but couldnot get it because of above reason
Account ac= new Account(1,100,25000);
ArrayList<Account>ac= new ArrayList<Account>();
ac.add(ac);
The whole point of your abstract class is to factorize some code in your application. Using it as a super type is in my opinion a bad practice since you should be using interfaces for that.
To get a complete response to your problem, I would:
Create an interface: Account.java
public interface Account {
public double deposit(double sum);
public double withdraw(double sum);
}
Create an abstract class: AbstractAccount.java
public abstract class AbstractAccount {
protected int accountId;
protected int customerId;
protected double balance;
public Account(int accountId, int customerId, double balance) {
this.accountId = accountId;
this.customerId = customerId;
this.balance = balance;
}
}
And finally provide a default implementation for your interface BankAccount.java
public class BankAccount extends AbstractAccount implements Account {
public Account(int accountId, int customerId, double balance) {
super(accountId, customerId, balance);
}
public double deposit(double sum) {
this.balance += sum;
}
public double withdraw(double sum) {
this.balance -= sum;
}
}
Then you should manipulate:
List<Account> accounts = new ArrayList<Account>();
accounts.add(new BankAccount(1, 1, 10000));
and never care about the implementing type :)
Abstract classes can't be instantiated, but they can be extended. If the child class is concrete, it can be instantiated.
You would also have to implement both your abstract methods to make the class concrete.
Read more here: Java inheritance.
You can add this following code just to get you started :
public class ConcreteAccount extends Account{
public ConcreteAccount (int accountId, int customerId, double balance) {
super(accountId, customerId, balance);
}
public abstract double deposit(double sum) {
//implementation here
}
public abstract double withdraw(double sum) {
//implementation here
}
}
Then after that, you can have :
Account ac= new ConcreteAccount(1,100,25000);
ArrayList<Account> acList= new ArrayList<Account>();
acList.add(ac);
Marking a class abstract means it might have unimplemented methods, therefore, you're not able to create an instance of an abstract class directly due to undefined behavior. What you can do is to define a non-abstract class which extends your Account class and implement the two abstract methods in Account. Something like class BankAccount extends Account { implementations }. After that, you can create instances of class BankAccount and add them into your ArrayList instance. Other instances of class that extends Account can also be added into your ArrayList instance.
When I use super() to use a superclass method, what is the proper way to return?
Let's say I have a class Hourly. It contains a constructor also called Hourly that has parameters "String name" and "double rate. The UML version looks like:
+Hourly(name:String, rate:double)
However, the "name" variable is a private attribute of the Employee class, of which the class hourly is related to via inheritance. By this I mean that the UML show a clear arrow (not a diamond) going from the class Hourly and pointing to the class Employee.
How would I write the constructor Hourly???
I have a basic skeleton of:
public Hourly(String name, double rate){
}
Please help me fill it in.
On a separate note, let's say that there was a return in a method. Say I wanted to return the double rate. What would be the proper syntax to return some that uses super() as I know I couldn't simply use:
return this.rate;
Your Employee surely has a name.
private String name;
public Employee(String name) {
this.name = name;
}
Following that, your Hourly must also have a name. Since an Hourly is-an Employee, you must set the name on it as well. That is accomplished like so.
public Hourly(String name, double rate) {
super(name);
this.rate = rate;
}
According to your comments, name is stored by the superclass; rate is not. So you should store rate in the Hourly class you're defining, while passing name to the super constructor, as follows:
public class Hourly {
private double rate;
public Hourly(String name, double rate) {
super(name);
this.rate = rate;
}
public double getRate() {
return rate;
}
}
If Hourly is sub class of Employee and if you want to parse the name to super class (Employee) then in your Hourly constructor call super(name);
public Hourly(String name, double rate){
super(name);
}
Since Hourly extends Employee:
class Hourly extends Employee {
private int rate;
public Hourly(String name, int rate) {
super(name); //assuming Employee has this constructor
this.rate = rate;
}
//this make sense if name is protected and doesn't have getter in base class
//ideally you would have this in base class itself
public String getName() {
return super.name; //for rate there is no sense in using super as it is not known to super class
}
}
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.
I'm trying to write a payroll program that simply receives input, does some calculations and displays the output for EACH employee.
I have two types of employees, hourly and salary. I created a class for each type that extends to an abstract employee class:
public abstract class Employee{
private String name;
private String type;
private int hours;
private double rate;
}
public class SalaryEmployee extends Employee{
public SalaryEmployee(String type, String name, int hours, double rate){
this.type = type;
this.name = name;
this.hours = hours;
this.rate = rate;
}
public void print(){
}
}
In my main method, when I try to create my objects using the code below:
Employee employee;
if(type.equals("hourly"))
{
employee = new HourlyEmployee(type, name, hours, rate);
}
else
{
employee = new SalaryEmployee(type, name, hours, rate);
}
I get the following error when I try to compile:
Lab3.java:53: not a statement
SalaryEmployee employee = new SalaryEmployee(type, name, hours, rate);
^
Lab3.java:53: ';' expected
SalaryEmployee employee = new SalaryEmployee(type, name, hours, rate);
^
2 errors
Any idea what is happening here? I've looked around for messing semi colons or braces, but haven't found anything yet.
Thanks for looking.
It is illegal to declare a variable in an if that does not use braces. It looks like what you meant to write is something like this:
Employee employee;
if(type.equals("hourly"))
employee = new HourlyEmployee(type, name, hours, rate);
else
employee = new SalaryEmployee(type, name, hours, rate);
Most coding conventions support always using braces after an if or else.
The only error I can see is that your SalaryEmployee class cannot access the base class variables because they are private. You should make them protected.
Although, the error you are getting would be different.. If you are still getting the error after changing, your error is probably lying elsewhere.