LSP introduction (LSP-liskov substitution principle)

Source: Internet
Author: User

1. LSP introduction (LSP -- liskov substitution principle ):Definition: if every object O1 of type S has an object O2 of type T, replace O2 with O1 for any program P defined with type T, P is a subtype of T. The child type must be able to replace its base type. Also known as LSP Lee's replacement principle.The general understanding of this principle is that the methods of the parent class must be implemented or rewritten in the subclass. Ii. Example:For the Dependency inversion principle, the parent class cannot depend on child classes, and both of them must depend on abstract classes. This dependency is the basis for code extension and runtime binding (polymorphism. Once a class user is dependent on a specific class, the extension of the dependency is impossible. If a class is dependent on an abstract class, only the subclass of the abstract class is implemented, can be used by class users to achieve system expansion.
However, the dependency inversion principle does not necessarily enable good scalability and runtime binding for our code. See the following code:

Public class animal
{
Private string name;
Public animal (string name)
{
This. Name = Name;
}
Public void description ()
{
Console. writeline ("This Is A (an)" + name );
}
} // Below is its sub-cat class:
Public class Cat: Animal
{
Public CAT (string name)
{

}
Public void MEW ()
{
Console. writeline ("the cat is saying like 'mew '");
}
} // Below is its subclass Dog class:
Public class Dog: Animal
{
Public dog (string name)
{}
Public void bark ()
{
Console. writeline ("the dog is saying like 'bark '");
}
} // Finally, let's look at the client call:
Public void decriptiontheanimal (animal)
{
If (typeof (animal) is cat)
{
Cat cat = (CAT) animal;
Cat. decription ();
Cat. MEW ();
}
Else if (typeof (animal) is dog)
{
Dog dog = (DOG) animal;
Dog. decription ();
Dog. Bark ();
}
} Through the code above, we can see that although the client dependency is abstract, the design's scalability is still poor and the binding is not implemented at runtime.
Why? In fact, this is because it does not meet the requirements of the Rys replacement principle. For example, CAT has no MEW () method parent class, and the dog class has no bark () method parent class, neither subclass can replace the parent class. This leads to poor system scalability and failure to bind during runtime. Now it seems that a system or subsystem must have good scalability and be bound during runtime. There are two necessary conditions: first, the dependency inversion principle; and second, the lining replacement principle. These two principles are indispensable. We know that in most of our modes, we all have a common interface, and then both the subclass and the extension class implement this interface. The following is a piece of original code:

If (action. Equals ("add "))
{
// Do add action
}
Else if (action. Equals ("view "))
{
// Do view action
}
Else if (action. Equals ("delete "))
{
// Do Delete action
}
Else if (action. Equals ("modify "))
{
// Do modify action
} The first thing we think of is to separate these actions and write the following code: public class addaction
{
Public void add ()
{
// Do add action
}
}
Public class viewaction
{
Public void view ()
{
// Do view action
}
}
Public class deleteaction
{
Public void Delete ()
{
// Do Delete action
}
}
Public class modifyaction
{
Public void modify ()
{
// Do modify action
}
} We can see that the code is independent from each other and satisfies the single responsibility principle, but this is far from enough because it does not meet the Dependency inversion principle and the Lee's replacement principle.
Next let's take a look at the solution to this problem in the command mode: public interface action
{
Public void doaction ();
}
// Then various implementations:
Public class addaction: Action
{
Public void doaction ()
{
// Do add action
}
}
Public class viewaction: Action
{
Public void doaction ()
{
// Do view action
}
}
Public class deleteaction: Action
{
Public void doaction ()
{
// Do Delete action
}
}
Public class modifyaction: Action
{
Public void doaction ()
{
// Do modify action
}
}
// In this way, the client call is roughly as follows:
Public void execute (action Action)
{
Action. doaction ();
} Check that the preceding client code has no such statements as typeof, and has good scalability and advantages of binding during runtime.

1. Ensure good scalability of the system or subsystem. Only when the child class can completely replace the parent class can the system or sub-system recognize the child class during the runtime, so that the system or sub-system has good scalability.
2. Realize binding during runtime, which ensures the smooth development of object-oriented polymorphism. This saves a lot of code duplication or redundancy. Avoid statements like instanceof or getclass (). These statements are taboo for Object-Oriented purposes.
3. It is conducive to implementing contractual programming. Contractual programming is conducive to system analysis and design. It refers to defining system interfaces during analysis and design and implementing these interfaces when coding. Define the functions that sub-classes need to implement in the parent class, and sub-classes only need to implement these functions.

Iii. Advantages of LSP:

  4. Notes for Using LSP:1. This principle is similar to the role of OCP. In fact, these basic object-oriented principles are two: 1: interface-oriented programming, not implementation-oriented; 2: combination without claiming inheritance 2. LSP is an important principle to ensure OCP
3. These basic principles also have a common layer in the implementation method, that is, using the intermediate interface layer to achieve low coupling of class objects, that is, abstract coupling! 4. Degraded functions of a derived class: some functions of a derived class are degraded (become useless). If the base user does not know that he or she cannot call f, the replacement violation will occur. The existence of a degraded function in a derived class does not always indicate a violation of the LSP, but it should be noted when this happens.
5. Throw an exception from the derived class: an exception that is not thrown if the base class is added to the method of the derived class. If the user of the base class does not expect these exceptions, adding them to the method of the derived class can lead to non-replacement.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.