1 min read

Guide to The Liskov Substitution Principle in Swift

The Liskov Substitution Principle (LSP) is a fundamental principle of object-oriented programming that states that objects of a superclass should be replaceable with objects of a subclass without altering the correctness of the program. This principle ensures that your code is flexible, maintainable, and extensible.

In this article, we will explore the Liskov Substitution Principle in Swift and see how we can implement it in our code.

Let's start with an example. Consider the following code snippet:

class Rectangle {
  var width: Double
  var height: Double

  init(width: Double, height: Double) {
    self.width = width
    self.height = height
  }

  func area() -> Double {
    return width * height
  }
}

class Square: Rectangle {
  override var width: Double {
    didSet {
      height = width
    }
  }

  override var height: Double {
    didSet {
      width = height
    }
  }

  init(side: Double) {
    super.init(width: side, height: side)
  }
}

In this example, we have a superclass Rectangle and a subclass Square that inherits from it. The Square class overrides the width and height properties to ensure that they always have the same value.

While this implementation may seem correct at first, it violates the Liskov Substitution Principle. This is because a Square cannot be substituted for a Rectangle without altering the correctness of the program.

Consider the following code snippet:

func printArea(rectangle: Rectangle) {
  print(rectangle.area())
}

let rectangle = Rectangle(width: 10, height: 5)
let square = Square(side: 5)

printArea(rectangle: rectangle) // Output: 50.0
printArea(rectangle: square) // Output: 25.0

n this example, we are passing both a Rectangle and a Square object to the printArea function. While the Rectangle object returns the correct area, the Square object returns an incorrect area.

To fix this, we can refactor our code to remove the Square class and create a separate Square struct that does not inherit from Rectangle.

struct Square {
  var side: Double

  func area() -> Double {
    return side * side
  }
}

let square = Square(side: 5)

print(square.area()) // Output: 25.0

With this refactored code, we have removed the violation of the Liskov Substitution Principle and ensured that our code is flexible, maintainable, and extensible.

In conclusion, the Liskov Substitution Principle is an essential principle of object-oriented programming that ensures that objects of a superclass can be replaced with objects of a subclass without altering the correctness of the program. By following this principle in our Swift code, we can create code that is flexible, maintainable, and extensible.