Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Solid Principles: Liskov Substitution Principle

DZone's Guide to

Solid Principles: Liskov Substitution Principle

Learn about the SOLID principles for programming (or refresh your memory) with this in-depth look at the Liskov Substitution Principle.

· DevOps Zone ·
Free Resource

Learn more about how CareerBuilder was able to resolve customer issues 5x faster by using Scalyr, the fastest log management tool on the market. 

Previously we took a dive into solid principles including the single responsibility and the open/closed principle. The Liskov substitution principle (LSP) is a particular definition of a subtyping relation, called (strong) behavioral subtyping,

Supposing object S is a subtype of object T, then objects of type T may be replaced with objects of type S without altering any of the desirable properties of T.

Suppose we have the Employee class.

package com.gkatzioura.solid.liskov;

public class Employee {

    public String getTitle() {
    return "The employee's title";
    }

    public void work() {

        System.out.println("Employee is working");
    }

} 

Also, we have another class which inherits the Employee class.

package com.gkatzioura.solid.liskov;

public class EmployeeOnVacation extends Employee {

    @Override
    public void work() {
        throw new IllegalArgumentException("Employees on vacation should not work");
    }
}

Supposing that we have a project.

package com.gkatzioura.solid.liskov;

import java.util.List;

public class Project {

    public void start(List<Employee> employees) {

        for(Employee employee:employees) {
            employee.work();
        }
    }
}

And we assign our employees to start working on it

List<Employee> employees = new ArrayList<>();
employees.add(new EmployeeOnVacation());
employees.add(new Employee());

Project project = new Project();
project.start(employees);

The outcome would be an exception due to the employee who is on vacation and thus the project will not be completed.

The employee on vacation is an employee, however, he will not work. Even if the method didn't throw an exception the method work would do nothing and this would affect delivering our project since our actual team's velocity is not the one we originally thought it was.

In order to avoid violating the principle, we shall use a different approach and change the class hierarchy.

We will change the original employee class.

package com.gkatzioura.solid.liskov;

public class Employee {

    public String getTitle() {
    return "The employee's title";
    }

} 

And we will make two different employee interfaces, the WorkingEmployee interface:

package com.gkatzioura.solid.liskov;

public interface WorkingEmployee {

    public void work();
}

And the non-working employee interface:

package com.gkatzioura.solid.liskov;

public interface NonWorkingEmployee {

    void relax();
}

Then the project will use only employees who are implementations of the WorkingEmployee interface and extend the employee class.

package com.gkatzioura.solid.liskov;

public class WorkingEmployeeImpl extends Employee implements WorkingEmployee {

    @Override
    public void work() {

    }
}
package com.gkatzioura.solid.liskov;

import java.util.List;

public class Project {

    public void start(List<WorkingEmployee> workingEmployees) {

        for(WorkingEmployee workingEmployee:workingEmployees) {
            workingEmployee.work();
        }
    }
}
List<WorkingEmployee> employees = new ArrayList<>();
employees.add(new WorkingEmployeeImpl());
Project project = new Project();
project.start(employees);

You can find the source code on GitHub. The next principle is the interface segregation principle.

Find out more about how Scalyr built a proprietary database that does not use text indexing for their log management tool.

Topics:
solid ,liskov substitution principle ,java ,devops ,programming

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}