Solid principles: 3. Liskov substitution principle

in #solid8 years ago

liskov-640x300.jpg

In my opinion, the Liskov principle is the hardest to understand, others often confuse it with other principles, let’s move on to the lesson.

What is Liskov basically about? In Wikipedia, you can find something like:

Functions that use pointers or references to base classes must also be able to use class objects that inherit from the base classes without having a thorough knowledge of these objects.

I already translate into human language 🙂

This means that any derived class can be used in a base class location, which means that it must always be 100% compatible with all methods and interfaces.

So in short:

Any derived class can be used in place of the base class (compatibility of all methods)

We break this rule, eg when the methods in the base class after which we inherit have nothing to do in the derived class that inherits from the base class, I will now show how it looks in practice in the code of our store.

namespace LiskovSubstitution
{
    abstract class TypeProduct
    {
        public int QuantityLiter { get; set; }
        public abstract void GetTypeProductsCount(int quantity);
        public abstract int ReturnQuantityLiter();
    }
 
    class Fruit : TypeProduct
    {
        public int NumberFruit { get; set; }
 
        public override void GetTypeProductsCount(int quantity)
        {
            NumberFruit += quantity;
        }
 
        public override int ReturnQuantityLiter()
        {
            // What? The weight of fruit is not measured in liters...
        }
    }
 
    class Drink : TypeProduct
    {
        public int NumberDrinks { get; set; }
 
        public override void GetTypeProductsCount(int quantity)
        {
            NumberDrinks += quantity;
        }
 
        public override int ReturnQuantityLiter()
        {
            return QuantityLiter;
        }
    }
}

In the above example, the mechanism of inheritance was wrongly planned, we created a new method in the TypeProductsInBag class, returning the amount of liters in a given product, however, the product is not always a drink, it can also be a fruit and fruits is not measured in liters and so it is breaking the Liskov principle.

Inheritance should be planned so that each derived class can use base class methods.

The principle of substitution Liskov is most often broken in cases:

  1. A poorly planned inheritance mechanism as in our example above.
  2. Application of inheritance without polymorphism.
  3. The derived classes replace the base class methods by overwriting them.

Derived classes should not override base class methods. They can possibly expand them, in C # this is done with the word base, which indicates the base class, look at the example below:

namespace LiskovSubstitution
{
    class Product
    {
        public virtual void PriceProduct(double price)
        {
            Console.WriteLine("This product costs: " + price + " PLN");
        }
    }
 
    class ElectronicsProduct : Product
    {
        public override void PriceProduct(double price)
        {
            base.PriceProduct(price);
            Console.WriteLine("Price description of only electronic product");
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
 
            while (true)
            {
                string getProduct = Console.ReadLine();
 
                if (getProduct == "bread")
                {
                    Product product = new Product();
                    product.PriceProduct(2.4);
                }
                else if (getProduct == "iphone7")
                {
                    ElectronicsProduct electronicsproduct = new ElectronicsProduct();
                    electronicsproduct.PriceProduct(3324.234);
                }
            }
 
            Console.ReadKey();
        }
    }
}

The above example follows the Liskov principle, you can use the base class method in a derived class and using it you do not overwrite it, only expand it.

Result:

liskovexam.png

You should also beware of such flowers💐:

static void Main()
{
    List<TypeProduct> typeproducts= new List<TypeProduct>();
 
    typeproducts.Add(new Fruit());
    typeproducts.Add(new Drink());
    typeproducts.Add(new Candys());
 
    foreach (TypeProducts obj in typeproducts)
    {
        if (obj is Drink)
            break; // We do not measure the amount of water in kilograms
 
        obj.GetKiloQuantity();
    }
}

Such a code is a sign that we inherit somewhere badly, because not all classes can be 100% substituted for the base type.

Summary

That’s all about Liskov Substitution principle.

Link to github with the whole code from this article: https://github.com/Slaw145/Liskov-substitution

This content also you can find on my blog http://devman.pl/programtech/solid-principles-3-liskov-substitution-principle/

If you recognise it as useful, share it with others so that others can also use it.

Leave upvote and follow and wait for next articles :) .

And NECESSERILY join the DevmanCommunity community on fb, part of the community is in one place 🙂

– site on fb: Devman.pl-Sławomir Kowalski

– group on fb: DevmanCommunity

Ask, comment underneath at the end of the post, share it, rate it, whatever you want🙂.

Sort:  

Hi! I am a robot. I just upvoted you! I found similar content that readers might be interested in:
http://devman.pl/en/programtech/solid-principles-3-liskov-substitution-principle/