SoFunction
Updated on 2025-03-07

C# realizes the six major design principles of Lisch replacement

definition:

1: If for each object o1 of type T1, there is an object o2 of type T2, so that when all programs P defined in T1 are replaced by all objects o1, the behavior of program P does not change, then type T2 is a subtype of type T1.

2: All places where base class reference must be able to use objects of its subclasses transparently.

The origin of the problem:

There is a function P1, which is completed by class A. Now it is necessary to expand the function P1, 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 subclass B of class A. Subclass B may cause the original function P1 to fail while completing the new function P2.

Solution:

When using inheritance, follow the principle of Richter replacement. When class B inherits class A, try not to do so except adding new methods to complete the new function P2.RewriteTry not to use parent class A methodReloadMethods of parent class A.

Inheritance contains the following meaning:

Any method that has been implemented in the parent class (relative to abstract methods) is actually setting a series of specifications and contracts. Although it does not force all subclasses to comply with these contracts, if the subclass arbitrarily modify these non-abstract methods, it will damage the entire inheritance system. The principle of Lizur replacement expresses this meaning.

Inheritance, as one of the three major object-oriented features, brings great convenience to programming, but also brings disadvantages. For example, using inheritance will bring invasiveness to the program, the portability of the program will be reduced, and the coupling between objects will be increased. If a class is inherited by other classes, when this class needs to be modified, all subclasses must be taken into account. After the parent class is modified, all functions involving subclasses may fail.

To illustrate the risk of inheritance, we need to complete the function of subtracting two numbers, and class A is responsible for:

class Program
    {
        static void Main(string[] args)
        {
            B b = new B();
            ("100+20={0}",(100, 20));
            ("100-20={0}",(100, 20));
            ();
        }
    }
    
    public class A
    {
        public int plus(int a, int b)
        {
            return a + b;
        }

        public int reduce(int a, int b)
        {
            return a - b;
        }
    }

    public class B : A
    {
        public new int reduce(int a, int b)
        {
            return a - b + 100;
        }
    }

Later, we added a new feature, requiring subtraction to add 100, which is done by Class B.

We found that the subtraction function that was originally running normally had an error. The reason is that when class B named the method, it accidentally rewrites the method of the parent class, causing all codes that run the subtraction function to call the method of the rewrite of class B.

This caused an error in the function that was originally running normally. In this example, after referring to the function completed by base class A and changing to subclass B, an exception occurred.

In actual programming, we often complete new functions by rewriting the parent class method. Although it is simple to write, the reusability of the entire inheritance system will be relatively poor, especially when polymorphism is used more frequently.

The probability of a program running error is very high. If you have to rewrite the parent class method, the more common approach is: the original parent class and child class inherit a more popular base class, remove the original inheritance relationship, and use dependency, aggregation, combination and other relationships instead.

PS: In simple terms, it is: a subclass can extend the functions of the parent class, but it cannot change the original functions of the parent class.

  • Subclasses can implement abstract methods of parent class, but cannot override non-abstract methods of parent class.
  • You can add your own unique methods to the subclass.
  • When a subclass method overloads the parent class's method, the preconditions of the method (i.e., the formal parameters of the method) are looser than the input parameters of the parent class method.
  • When a method of a child class implements the abstract method of the parent class, the postcondition of the method (i.e., the return value of the method) is more stringent than the parent class.

This is what this article about C# implementing the six major design principles of Lissian replacement. I hope it will be helpful to everyone's learning and I hope everyone will support me more.