0

Sometimes I get often confused between when to derive class(use inheritance) and when not to.So for instance I have a code like this :

public class Payroll
{
    public void ProcessPayroll(Employee e) //abstraction
    {
         e.ProcessPayroll();
    }
}

Class Employee : Payroll
{
    public virtual void ProcessPayroll()
    {
       //Process Payroll
    }
}

class FulltimeEmployee : Employee
{
    public override void ProcessPayroll()
    {
       //Payroll processing based on fulltime employee
    }
}

This make sense :

class FulltimeEmployee : Employee

Becuase FulltimeEmployee is a Employee so IS-A relationship holds true here.

But I am confused here for below relationship so as to does this inheritance make sense as it is not an "IS-A" relationship ?

Class Employee : Payroll

Also Inheritance always have to follow IS-A relationship ?

Another Example :

Requirement says "Employee cannot exist without Company"

Based on this I did this :

public class Company

public class Employee : Company

Now does this make sense ?

Update :

I think above can be better represented using Aggregation :

public class Company
{ 
    Employee E; //because Company has-a Employee
}

But tomorrow if requirement says Company can exist without Employee too that means I have to come to this class and update the code.

Isnt this will violate Open and Closed principle ?

Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
I Love Stackoverflow
  • 6,738
  • 20
  • 97
  • 216
  • 4
    An employee is not a payroll. There should be no inheritance relationship there. An employee might be *on* a payroll, but that's not the same thing. – Andy Turner Jun 12 '19 at 07:17
  • Is an `Employee` a special type of `Payroll`? It doesn't sound like this is the case. – ProgrammingLlama Jun 12 '19 at 07:17
  • 1
    inheritance is an "IS-A" relationship. Class (implementation) inheritance is a special case - there are also interfaces in Java which may be better suited. "Employee is a company" or "Employee is a payroll" don't make sense. – Erwin Bolwidt Jun 12 '19 at 07:18
  • @AndyTurner Yes you are right but Employee is a part of payroll process.So I am trying to understand whether Is-A relationship is compulsory for inheritance or not – I Love Stackoverflow Jun 12 '19 at 07:18
  • @ILoveStackoverflow By using inheritance you are representing `Employee` as a specialised type of `Payroll`, and indeed of `Company` in your other example. – ProgrammingLlama Jun 12 '19 at 07:21
  • @John Employee and Payroll are 2 seperate process and Employee is a part of payroll process.Actually this is what I am trying to understand and figure out whether Is-A relationship should always holds true for inheritance – I Love Stackoverflow Jun 12 '19 at 07:21
  • @AndyTurner I have updated question with 1 more doubt.Can you please shed some lights on it – I Love Stackoverflow Jun 12 '19 at 07:24
  • @ErwinBolwidt I have updated question with 1 more doubt.Can you please shed some lights on it – I Love Stackoverflow Jun 12 '19 at 07:25
  • @ILoveStackoverflow Employee(s) should be a list, unless you expect the Company you represent to only ever have one employee. The open / closed principle says your class should be open for _extension_ and closed for _modification_. I don't see how that violates it. – ProgrammingLlama Jun 12 '19 at 07:27

2 Answers2

3

Requirement says "Employee cannot exist without Company" it means company has a employees. Has-A relationship is also known as composition. You don't require this Class Employee : Payroll. It should be just class Employee.

In Payroll class, Employee object is injected, so it can process on instant methods. Also for good practice follow this Prefer composition over inheritance?

Answer for updated part: Open close principal says "Class is open for extension but closed for modification"

public class Company
    {
        private readonly IEmployee e;
        public Company(IEmployee e)
        {
            this.e = e;
        }
    }
    public interface IEmployee
    { //Some employee related methods
    }

Here you have injected IEmployee in Company class. Now you can extend Company class functionality using instant of IEmployee. Look at Strategy Pattern example, which hopefully clarified your doubt Real World Example of the Strategy Pattern

Gopu_Tunas
  • 174
  • 2
  • 14
1

What you are talking is rather HAS-A relationship, so you need composition:

public class Employee
{
  Payroll payroll;
  Company company;
  ...
}

As every employee is hired somewhere, so it has a company he works at.

On the other side, company has employees, so it could be designed as well as:

public class Company
{
  List<Employee> employees;
  ...
}

You need to prepare yoursef also for situation where Employee has no Company or vice versa, then respective fields in classes would be null, Considering that, you need to write your methods with null checks to handle such situation, like:

if(employees == null || employeses.Count == 0)
  Console.WriteLine("Sorry, company has no employees!");
Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
  • But tomorrow if requirement says Company can exist without Employee too than I have to come to Company class and update the code.Isnt this violating Open/Closed principle? – I Love Stackoverflow Jun 12 '19 at 07:26
  • @ILoveStackoverflow Then company should have `employees = null` and in functions using `employees` you should handle case, when this field is `null`. With such design, it would be closed for modification. – Michał Turczyn Jun 12 '19 at 07:35
  • Can you show me in the code,How to handle both the requirement properly without violating Open/Closed principle please. – I Love Stackoverflow Jun 12 '19 at 07:49