Explain:
There must have been a lot of doubts about the name of this principle as I have just seen it. The reason is that the principle was first introduced in 1988 by a woman surnamed Barbara Liskov of MIT.
Definition 1: If for each object of type T1, there is an object O2 of type T2, so that all program P defined by T1 is replaced with O1 for all objects O2, the behavior of program p does not change, then type T2 is a subtype of type T1.
definition 2: All references to base classes must be able to transparently use objects of their subclasses.
problem Origin: There is a functional P1, which is done by Class A. Now need to extend the function P1, the function of the extension is P, where p is composed of the original function P1 and the new function P2. The new function p is done by subclass B of Class A, and sub-class B, while completing the new function P2, may cause the original function P1 to fail.
example:
Class ca{public: ca () {} int func1 (int a, int &NBSP;B) { return a-b; &NBSP;&NBSP;&NBSP;}};CLASS&NBSP;CB&NBSP;:&NBSP;PUBLIC&NBSP;CA{PUBLIC:&NBSP;&NBSP;&NBSP;&NBSP;CB () {} &NBSP;&NBSP;&NBSP;INT&NBSP;FUNC1 (INT&NBSP;A,&NBSP;INT&NBSP;B,&NBSP;QSTRING&NBSP;STR) { return a+b; } &NBSP;INT&NBSP;FUNC2 (int a, int b) { return func1 (A, B, "-") +100; }};int main (Int argc, char *argv[]) { qcoreapplication a (ARGC,&NBSP;ARGV); cb* &NBSP;B&NBSP;=&NBSP;NEW&NBSP;CB (); qdebug () << "100-50=" << &NBSP;B->FUNC1 (100,&nbsP;50) qdebug () << "100-80=" << b->func1 (100, qdebug () << "100+20+100=" << b->func2 (100,&NBSP;20); return a.exec ();}
It turned out to be a surprise!
Solution: Follow the Richter substitution principle when using inheritance. When Class B inherits from Class A, try not to rewrite the parent class A's method, but also try not to reload the parent Class A's method, except to add a new method to complete new functionality P2.
Inheritance contains a layer of meaning: in a parent class, a well-implemented method (as opposed to an abstract method) is actually a set of specifications and contracts, although it does not enforce that all subclasses must comply with these contracts, but if the subclasses arbitrarily modify these non-abstract methods, the entire inheritance system will be destroyed. The principle of replacing the Richter scale is to express this level of meaning.
As one of the three characteristics of object-oriented, inheritance brings great convenience to program design, and it also has drawbacks. For example, the use of inheritance will be intrusive to the program, the portability of the program, increase the coupling between objects, if a class is inherited by other classes, when the class needs to be modified, must take into account all subclasses, and after the parent class modification, all the functions that involve subclasses are likely to fail.
Code First: #include <QCoreApplication>
#include <QDebug>
#include <iostream>
using namespace Std;
, soldiers, scene design
Class Abstractgun
{
Public
virtual void shoot ()
{
cout << "Kill people!";
}
};
Class Handgun:public Abstractgun
{
Public
virtual void shoot ()
{
cout << "handgun kill";
}
};
Class Rifle:public Abstractgun
{
Public
virtual void shoot ()
{
cout << "Rifle Kill";
}
};
Class Machinegun:public Abstractgun
{
Public
virtual void shoot ()
{
cout << "machinegun kill";
}
};
Class Soldier
{
Public
void Setgun (abstractgun* _gun)
{
M_gun = _gun;
}
virtual void Killenemy ()
{
M_gun->shoot ();//This is good, you can perform virtual functions separately.
}
Virtual ~soldier () {}
Protected
abstractgun* M_gun;
};
When the new class "Toy gun" was added, the toy was shot dead, unable to perform killenemy and so on.
If a subclass cannot implement the method of the parent class completely,
It is recommended that you break parent-child relationships and replace inheritance with dependencies, aggregates, and combinations.
Class Toygun
{
Public
/////......./////
};
Subclasses can have their own personalities.
Class Aug:public Rifle
{
Public
void Zoomeout ()
{
cout << "observed enemy\n";
}
virtual void shoot ()
{
cout << "kill\n";
}
};
Add * * *, to give a sniper, my own design derivation (perhaps other circumstances are not allowed it)
Class Snipper:public Soldier
{
Public
virtual void Killenemy ()
{
aug* static_cast<aug*> (M_gun);
Aug->zoomeout ();
Aug->shoot ();
}
};
This uses static, which means that the external domain can be called directly to the field, for ease of setting.
static void Action ()
{
snipper* shibin = new Snipper;
Shibin->setgun (new);
Shibin->killenemy ();//Start Kill
}
int main (int argc, char *argv[])
{
Qcoreapplication A (argc, argv);
Action ();
return A.exec ();
}
To summarize:
The principle of the Richter substitution is popular: subclasses can extend the functionality of the parent class, but cannot change the original functionality of the parent class. it contains the following 4 levels of meaning:
Subclasses can implement the abstract methods of the parent class, but cannot override the non-abstract methods of the parent class.
Subclasses can add their own unique methods.
When a method of a subclass overloads a method of the parent class, the method's preconditions (that is, the parameter of the method) are more lenient than the input parameters of the parent class method.
When a method of a subclass implements an abstract method of the parent class, the post condition of the method (that is, the return value of the method) is stricter than the parent class.
This article is from the "GDT Commentary" blog, make sure to keep this source http://844133395.blog.51cto.com/3483632/1750354
Six principles of the Richter scale substitution principle