Spis treści
Liskov substitution principle
The application should work correctly when we put in the base class place every derived class.
How to use the LSP principle in practice?
Think carefully before taking advantage of the inheritance. Usually, a better option is to use composition. Try to do a simple experiment: put in the classes using our class tree, all posterity classes and the base class, and see if the program still behaves properly, or if it only expects one particular type of class.
Example
Let’s consider this task:
We have an application, which shows a video from a camera. To our application, we can connect many camera types. Not every we can handle. Fortunately, we knot it at the beginning. We create base class Camera and inherit its in special camera classes (and in not handled camera too).
class Program { static void Main(string[] args) { var cameras = new List<Camera>(); var cameraNC1 = new CameraNC1("Front camera"); cameras.Add(cameraNC1); var cameraShower = new CameraShower(cameraNC1); cameraShower.Show(); var cameraNC2 = new CameraNC2("Back camera"); cameras.Add(cameraNC2); cameraShower = new CameraShower(cameraNC2); cameraShower.Show(); var unsupportedCamera = new UnsupportedCamera(null); cameras.Add(unsupportedCamera); cameraShower = new CameraShower(unsupportedCamera); cameraShower.Show(); } } internal class CameraShower { private Camera camera; public CameraShower(Camera camera) { this.camera = camera; } internal void Show() { if (!(camera is UnsupportedCamera)) Console.WriteLine($"Camera name: {camera.GetName()}"); } } internal class CameraNC2 : Camera { public CameraNC2(string name) : base(name) { } } internal class CameraNC1 : Camera { public CameraNC1(string name) : base(name) { } } internal class UnsupportedCamera : Camera { public UnsupportedCamera(string name) : base(name) { } internal override string GetName() { throw new Exception("This camera does not have name. It is not supported."); } } internal abstract class Camera { protected readonly string name; public Camera(string name) { this.name = name; } internal virtual string GetName() { return name; } }
Everything working well. But, when for not handling a camera we should make a special checking. We can improve it and implement GetName method in different way.
class Program { static void Main(string[] args) { var cameras = new List<Camera>(); var cameraNC1 = new CameraNC1("Front camera"); cameras.Add(cameraNC1); var cameraShower = new CameraShower(cameraNC1); cameraShower.Show(); var cameraNC2 = new CameraNC2("Back camera"); cameras.Add(cameraNC2); cameraShower = new CameraShower(cameraNC2); cameraShower.Show(); var unsupportedCamera = new UnsupportedCamera(); cameras.Add(unsupportedCamera); cameraShower = new CameraShower(unsupportedCamera); cameraShower.Show(); } } internal class CameraShower { private Camera camera; public CameraShower(Camera camera) { this.camera = camera; } internal void Show() { Console.WriteLine($"Camera name: {camera.GetName()}"); } } internal class CameraNC2 : Camera { public CameraNC2(string name) : base(name) { } } internal class CameraNC1 : Camera { public CameraNC1(string name) : base(name) { } } internal class UnsupportedCamera : Camera { public UnsupportedCamera() : base("Unknown - this camera is not supported") { } } internal abstract class Camera { protected readonly string name; public Camera(string name) { this.name = name; } internal virtual string GetName() { return name; } }
All posts from mini project: Learn SOLID and OOP principles:
- SOLID
- SOLID exercises
- S like Single responsibility principle
- SOLID exercises — Kata
- O as Open-closed principle
- L jak Liskov Substitution Principle
- Interface segregation principle
- KISS — Keep it simple, stupid
- DRY — Don’t repeat yourself
- Dependency inversion principle
- SLAP — Single Level of Abstraction Principle
- Composition Over Inheritance
- Encapsulate what changes
- Lod — Law of Demeter
- ES as Exercises of Single responsibility principle
- EO as Exercises of Open/closed principle
- EL as Exercises of Liskov Substitution Principle
- EI as Eexrcises of Interface segregation principle
- ES as Exercises of Dependency Inversion Principle
- Object-oriented programming
- OOP — Object-Oriented Programming — Advice
- OOP — Object Oriented Programming
Sources
Main image
Materials
- Clean Architecture — Robert C. Martin
- https://medium.com/hackernoon/the-liskov-substitution-principle-and-why-you-might-want-to-enforce-it-6f5bbb05c06d
- https://code.tutsplus.com/tutorials/solid-part-3-liskov-substitution-interface-segregation-principles–net-36710