0

I'm implementing a basic payroll program in Java. I have an abstract super class called Employee that mainly stores data like tax ID, name, etc. I then have 2 subclasses of Employee called Hourly and Salaried which are supposed to represent types of employee. Those two classes implement calculations of pay and tax, and store data specific to their employee types.

The trouble is, I'm ending up with heaps of fields as new fields need to be implemented to store the calculated pay, tax, etc. Would I be justified in getting rid of Salaried and Hourly and creating a new super class, PayCalculation, then having PayHourly and PaySalaried classes stemming off this to implement the hourly/salaried specific fields and calculations? If so, would it make sense to have a composition relationship between Employee (super class) and PayCalculation (subclass)?

I don't have a great understanding of composition. If anyone could think of a better way to structure this I would much appreciate it.

I don't know how to use UML, but here's a pretty shoddy diagram I made in paint to explain this.

enter image description here

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
false_azure
  • 1,333
  • 4
  • 25
  • 46
  • This link would be useful for you. **http://stackoverflow.com/q/2399544/1115584** – AmitG Apr 08 '13 at 07:30
  • Thanks. I kind of feel like I'm unjustified in using composition (I'm not sure if it's a has-a relationship). Yet, I'm not sure how to structure it another way. Should I revert to the previous structure? – false_azure Apr 08 '13 at 07:35

3 Answers3

2

Yes it do make sense to have composition rel'ship between Employee and PayCalculation. Think this problem in a practical way as - Employee will have payCalculations, workingHourCalculations etc.. as fields/compositions but not the other way around.

Also Employee can have abstract methods to calculate pay, work etc. The instance fields of Employee can hold members needed to calculate pay, work etc.

Public Employee {
    private Map payCalMap;
    .....
    public double calculatePay();    
}
Ezhil V
  • 894
  • 5
  • 11
  • This looks good too. I'm not sure which of the two answers I should implement. – false_azure Apr 08 '13 at 07:43
  • This is just a sample. You can use any type of Datastructure that suits the purpose. or Even your own custom datastructure implementation. – Ezhil V Apr 08 '13 at 07:48
  • Things like Pay calculation can be placed in a separate helper method in any utility class. This is because the calculation will be common and can be reused across. – Ezhil V Apr 08 '13 at 07:50
2

Employee, Salaried(Employee) and Hourly(Employee) are perfectly suited as classes.

PayCalculation(), PayHourly(), and PaySalaried() sound more like methods though, right?

So what you can do is create an abstract method (meaning you don't actually implement it) PayCalculation() in the superclass (Employee). Then you can (and indeed will have to) write the implementation of PayCalculation() in your Salaried and Hourly classes.

This means that, when you call PayCalculation() on an Hourly object, it will do an entirely different thing than it will when you call PayCalculation() on a Salaried object.

Does this make sense? Really think deeply about these concepts - trying to grasp the concepts of inheritance is really trying to grasp the concept of object-oriented programming in general.

Please let me know if I can explain anything differently - it wasn't long ago that I was wrapping my head around these same concepts.

Also, you're correct in your comment above. There is not a "has a" relationship between Employee and Hourly/Salaried. The relationship that exists between them is an "is a" relationship: An hourly employee IS A employee. This means that you need to be thinking about inheritance, not composition - which is exactly what we've been talking about here.

That should be the takeaway from this question: What you're trying to grasp is inheritance, not composition.

drew moore
  • 31,565
  • 17
  • 75
  • 112
  • Thanks, this was what I had before. Does it matter that I end up with ~10 fields in my Employee class? – false_azure Apr 08 '13 at 07:41
  • Not. At. All. Funny, I remember I had the same worry in one of my first programs (which was actually very similar in nature to this one). When I asked my professor this same question, he told me that there is no amount of fields that is universally "too many" or "too few". The appropriate number for any given class is however many it needs - no more and no less. – drew moore Apr 08 '13 at 07:43
  • ok, cool! I guess if I ended up with bajillions (which I won't) I could just store the data in some sort of data structure or something. – false_azure Apr 08 '13 at 07:44
  • :) Forget about those considerations for now. At this stage, forget about performance / efficiency - focus on the core concepts of object orientation, and on designing clear, readable and sensible logical architectures. The other stuff will fall into place later. – drew moore Apr 08 '13 at 07:47
  • See my edit above (the last paragraph) if you haven't yet. – drew moore Apr 08 '13 at 07:48
  • Thanks again. This is indeed for a first OOP project, so the focus is supposed to be on the concepts of object orientation. – false_azure Apr 08 '13 at 07:51
  • You got it. Grasp the fundamentals - the few big ideas. Once you do, the many small ideas will come quite naturally. A heads up since you're new here - if my answer (or anyone else's) was helpful, feel free to accept it: doing so gives you +2 reputation points, and increases the likelihood that folks will help you out in the future. – drew moore Apr 08 '13 at 07:53
  • Creating SalariedEmployee and HourlyEmployee classes that inherit from Employee is fine IF you're OK with the ramifications when handling the case where a salaried employee becomes an hourly employee or vice versa (which certainly happens in the real world). Inheritance in this case is probably fine for most apps, but not all. See this blog post: http://www.briankotek.com/blog/index.cfm/2007/5/9/The-Real-Power-of-Inheritance – Matt Browne Aug 11 '13 at 00:13
2

Employee's class delegates payment calculation to PayCalculation interface method calculate().

By substitution of implementation of this interface you could achieve different behaviour.

class Employee {
  private PayCalculation payCalculation;
  public Employee(PayCalculation calculation){
    this.calculation = calculation;
  }

  public void calculatePayment(){
    payCalculation.calculate();
  }
}

public interface PayCalculation{
  public void calculate();
}

class PayHourly implements PayCalculation{
  public void calculation(){
    System.out.println("Hourly-paid");
  }
}

class PaySalaried implements PayCalculation{
  public void calculate(){
    System.out.println("Salary-paid");
  }
}

Then you create 2 distinct employees with different payment systems:

Employee salaryPaidEmployee = new Employee(new PaySalaried());
Employee hourlyPaidEmployee = new Employee(new PayHourly());

and calculate payment based on Payment system:

 salaryPaidEmployee.calculatePayment();
 hourlyPaidEmployee.calculatePayment();
Sergii Shevchyk
  • 38,716
  • 12
  • 50
  • 61