Take advantage of Liskov Substitution Principle to reduce coupling and facilitate code reusability in your application The term SOLID is a popular acronym used to refer to a set of five principles of software architecture. These include: SRP (Single Responsibility), Open/Close, Liskov’s Substitution, Interface Segregation, and Dependency Inversion. LSP (Liskov Substitution Principle) is a fundamental principle of OOP and states that derived classes should be able to extend their base classes without changing their behavior. In other words, derived classes should be replaceable for their base types, i.e., a reference to a base class should be replaceable with a derived class without affecting the behavior. The Liskov Substitution Principle represents a strong behavioral subtyping and was introduced by Barbara Liskov in the year 1987. According to Barbara Liskov, “What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.” A classic example of violation of the Liskov Substitution Principle is the Rectangle – Square problem. The Square class extends the Rectangle class and assumes that the width and height are equal. Consider the following class. The Rectangle class contains two data members — width and height. There are also three properties — Height, Width, and Area. While the first two properties set the height and the width of the rectangle, the Area property has a getter that returns the area of the rectangle. class Rectangle { protected int width; protected int height; public virtual int Width { get { return width; } set { width = value; } } public virtual int Height { get { return height; } set { height = value; } } public int Area { get { return height * width; } } } A Square is a type of rectangle all of whose sides are of equal size, i.e., the width and height of a Square is the same. class Square : Rectangle { public override int Width { get { return width; } set { width = value; height = value; } } public override int Height { get { return width; } set { width = value; height = value; } } } Consider another class called ObjectFactory. class ObjectFactory { public static Rectangle GetRectangleInstance() { return new Square(); } } Note that the setters for the Width and Height properties in the Square class have been overridden and modified to ensure that the height and width are the same. Let’s now create an instance of the Rectangle class using and set its height and width properties. Rectangle s = ObjectFactory.GetRectangleInstance(); s.Height = 9; s.Width = 8; Console.WriteLine(s.Area); The above code snippet when executed would display the value 64 in the console. The expected value is 72 since the width and height mentioned is 9 and 8 respectively. This is a violation of the Liskov Substitution Principle. This is because the Square class that has extended the Rectangle class has modified the behavior. To ensure that the Liskov Substitution Principle is not violated, the Square class can extend the Rectangle class but shouldn’t modify the behavior. The behavior has been changed by modifying the setters for both the properties Width and Height. The values of height and width are same if it is a Square — they shouldn’t be the same if it is a Rectangle. How do we fix this, i.e., ensure that this principle is not violated? Well, you can have a new class introduced called Quadrilateral and ensure that both the Rectangle and the Square classes extend the Quadrilateral class. public class Quadrilateral { public virtual int Height { get; set; } public virtual int Width { get; set; } public int Area { get { return Height * Width; } } } Now, both the Rectangle and Square classes should extend the Quadrilateral class and set the values of the Width and Height properties appropriately. In essence, the derived classes should have the necessary functionality to set values to these properties based on the type of the Quadrilateral instance you need to calculate area for. Note that both the Height and Width properties have been marked as virtual in the Quadrilateral class meaning that these properties should be overridden by the classes that derive the Quadrilateral class. Liskov Substitution Principle is an extension of the Open Close Principle and is violated when you have written code that throws “not implemented exceptions” or you hide methods in a derived class that have been marked as virtual in the base class. If your code adheres to the Liskov Substitution Principle you have many benefits. These include: code re-usability, reduced coupling, and easier maintenance. Related content feature What is Rust? Safe, fast, and easy software development Unlike most programming languages, Rust doesn't make you choose between speed, safety, and ease of use. Find out how Rust delivers better code with fewer compromises, and a few downsides to consider before learning Rust. By Serdar Yegulalp Nov 20, 2024 11 mins Rust Programming Languages Software Development how-to Kotlin for Java developers: Classes and coroutines Kotlin was designed to bring more flexibility and flow to programming in the JVM. Here's an in-depth look at how Kotlin makes working with classes and objects easier and introduces coroutines to modernize concurrency. By Matthew Tyson Nov 20, 2024 9 mins Java Kotlin Programming Languages analysis Azure AI Foundry tools for changes in AI applications Microsoft’s launch of Azure AI Foundry at Ignite 2024 signals a welcome shift from chatbots to agents and to using AI for business process automation. By Simon Bisson Nov 20, 2024 7 mins Microsoft Azure Generative AI Development Tools news Microsoft unveils imaging APIs for Windows Copilot Runtime Generative AI-backed APIs will allow developers to build image super resolution, image segmentation, object erase, and OCR capabilities into Windows applications. By Paul Krill Nov 19, 2024 2 mins Generative AI APIs Development Libraries and Frameworks Resources Videos