This is the sixth day of my participation in the August More text Challenge. For details, see: August More Text Challenge

The Richter substitution principle, which defines the specification for inheritance.

The Richter substitution principle has the following characteristics:

Code sharing, reducing the effort to create classes

Improve code reuse

Improve code extensibility

Improve the openness of product code

Inheritance intrusive As long as you inherit, you must own the content of the parent class

To reduce the flexibility of the code, subclasses must have the properties and methods of the parent class

Increase coupling.

Richter’s substitution principle:

One function, P1, is done by class A. Now function P1 needs to be extended, and the extended function is P, where P consists of the original function P1 and the new function P2. The new function P is completed by the subclass B of class A, so when subclass B completes the new function P2, it may cause the failure of the original function P1. When using inheritance, follow the Richter substitution principle. When class B inherits from class A, in addition to adding new methods to complete the added function P2, try not to override the methods of the parent class A, and try not to override the methods of the parent class A.

Here’s an example:

I have here a rectangle class, a square class, and a square is a special rectangle. So the square class inherits from the rectangle class:

The code looks like this:

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
  
namespace Displace
{
    /// <summary>
    ///High-level modules: Call rectangle and square classes
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            Rectangle rectangle = new Rectangle();
            rectangle.SetHeight(10);
            rectangle.SetWidth(20);
            Console.WriteLine(rectangle.GetHeight());
            Console.WriteLine(rectangle.GetWidth());
  
            Console.WriteLine("------------ I am the dividing line -------------");
  
            Square square = new Square();
            square.SetHeight(10);
            square.SetWidth(20); Console.WriteLine(square.GetHeight()); Console.WriteLine(square.GetWidth()); Console.ReadKey(); }}}Copy the code

Rectangle class: Rectangle. Cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
  
namespace Displace
{
    /// <summary>
    ///Rectangle class
    /// </summary>
    public class Rectangle
    {
        public double height;
        public double width;
  
        public void SetHeight(double height)
        {
            this.height = height;
        }
  
        public double GetHeight()
        {
            return height;
        }
  
        public void SetWidth(double width)
        {
            this.width = width;
        }
  
        public double GetWidth()
        {
            returnwidth; }}}Copy the code

Square class: square.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
  
namespace Displace
{
    /// <summary>
    ///A square class
    /// </summary>
    public class Square: Rectangle
    {
        public void SetHeight(double height)
        {
            this.height = height;
            this.width = height;
        }
  
        public double GetHeight()
        {
            return height;
        }
  
        public void SetWidth(double width)
        {
            this.height = width;
            this.width = width;
        }
  
        public double GetWidth()
        {
            return width;
        }
  
        /// <summary>
        ///With area
        /// </summary>
        public double GetArea()
        {
            returnwidth * height; }}}Copy the code

The output is shown in the figure below:

The result of the output is obviously wrong, I call the uniform method of the parent class and the child class output should be the same. So the chestnuts on top don’t conform to the Richter substitution principle.

The Richter substitution principle: wherever there is a parent class, it can be replaced by a child class without any errors or exceptions. But not the other way around. Where a subclass appears, it cannot be replaced by a subclass. There are four constraints: 1: A child class must implement an abstract method of its parent class, but must not override a non-abstract (implemented) method of its parent class. Sometimes a superclass has more than one subclass, but there is a special case within these subclasses. In order to satisfy both the Richter substitution principle and the function of the subclass, some partners may modify the methods of the superclass. However, changing a method in a parent class can cause more errors in other subclasses. How do we do that? We can create a new superclass for this particular case that has some of the functions of the original but has different functions. This satisfies both the Richter substitution principle and the need for this particular case. 2: Subclasses can add their own methods. 3: When a subclass overrides or implements a superclass method, the preconditions of the method (that is, the parameters of the method) are more relaxed than the input parameters of the superclass method. 4: 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 that of the parent class.

Me on the above procedure is obviously not in conformity with the substitution principle on the Richter scale, so we how to modify the program above, we create an interface, the interface contains for the width and height of the two methods, rectangle and square, this interface is implemented, then the both for now, at the same level of parent can place, they both can. Here is the code I modified:

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
  
namespace Displace
{
    /// <summary>
    ///High-level modules: Call rectangle and square classes
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            Rectangle rectangle = new Rectangle();
            rectangle.SetHeight(10);
            rectangle.SetWidth(20);
            Console.WriteLine(rectangle.GetHeight());
            Console.WriteLine(rectangle.GetWidth());
  
            Console.WriteLine("------------ I am the dividing line -------------");
  
            Square square = new Square();
            square.SetHeight(10);
            square.SetWidth(20); Console.WriteLine(square.GetHeight()); Console.WriteLine(square.GetWidth()); Console.ReadKey(); }}}Copy the code

Rectangle.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
  
namespace Displace
{
    /// <summary>
    ///Rectangle class
    /// </summary>
    public class Rectangle: Interface1
    {
        public double height;
        public double width;
  
        public void SetHeight(double height)
        {
            this.height = height;
        }
  
        public double GetHeight()
        {
            return height;
        }
  
        public void SetWidth(double width)
        {
            this.width = width;
        }
  
        public double GetWidth()
        {
            returnwidth; }}}Copy the code

Square.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
  
namespace Displace
{
    /// <summary>
    ///A square class
    /// </summary>
    public class Square: Interface1
    {
        public double height;
        public double width;
        public void SetHeight(double height)
        {
            this.height = height;
            this.width = height;
        }
  
        public double GetHeight()
        {
            return height;
        }
  
        public void SetWidth(double width)
        {
            this.height = width;
            this.width = width;
        }
  
        public double GetWidth()
        {
            return width;
        }
  
        /// <summary>
        ///With area
        /// </summary>
        public double GetArea()
        {
            returnwidth * height; }}}Copy the code

Parent interface: interface1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
  
namespace Displace
{
    interface Interface1
    {
        double GetHeight();
        double GetWidth(); }}Copy the code

This program basically implements the four constraints described above. The example is a little bad, but it basically incorporates the idea of the Richter substitution principle.

After all, the Richter substitution principle is a constraint on inheritance

Welcome to guanchao.site

Welcome to applet: