SoFunction
Updated on 2025-03-07

C# object-oriented three major features: encapsulation, inheritance, and polymorphism

Object-oriented has three characteristics: encapsulation, inheritance, and polymorphism. Object-oriented programming manages complex things according to the characteristics of the real world, abstracts them into objects, has its own state and behavior, and completes tasks through reactions to messages. This programming method provides very powerful diversity, greatly increases the opportunity for reusing code, increases the speed of program development, and wraps program code that is independent and unique, so that other parts of the program will not affect other parts of the program when modifying some program code.

1. Packaging

Each object contains all the information needed for it to operate, encapsulates only the external interface of the code unit, hides its specific implementation, and tries not to disclose the code to the public. There are many benefits to using encapsulation. From a design perspective, encapsulation can block some important information from the outside. For example, people who use computers only need to know how to use the computer, without knowing how these functions are implemented specifically; from the perspective of security, encapsulation makes the code more secure and easy to modify. encapsulation clearly points out which attributes and methods are accessible externally. In this way, when it is necessary to adjust the code of this class, as long as the public attributes are not changed, the parameters and return value types of public methods remain unchanged, then the class can be modified as much as possible without affecting other parts of the program; encapsulation also avoids the problem of naming conflicts, encapsulation has an isolation function, and different classes can have methods and attributes with the same name, but they will not be confused, and coupling can be reduced.

2. Inheritance

Inheritance can use all the functions of an existing class and extend these functions without having to rewrite the original class. Classes produced using inheritance are called derivative classes or subclasses, while inherited classes are called base classes or superclasses or parent classes. Inheritance means that a type is derived from a base type, which has all member fields and functions of the base type, and its subclass is an extension to the parent class; interface inheritance means that a type only inherits the signature of the function and does not inherit any implementation code. Inheritance divides the hierarchy of classes. It can also be said that inheritance is a grouping of classes. The parent class represents abstract classes and more commonly used classes, while the subclass represents more concrete and refined classes. Inheritance is an important means to realize code reuse and expansion. The so-called abstract class refers to a class that is associated with specific matters but only expresses the whole rather than a specific concept. For example, shapes include squares, rectangles, circles, etc. At this time, shapes are an abstract concept, equivalent to a parent class, while squares, rectangles, and circles are concrete shapes, equivalent to subclasses.

3. Polymorphism

Polymorphism refers to the situation where different methods with the same name coexist in a program, and polymorphism is mainly achieved through the subclass override of parent class methods. In this way, different types of objects can complete specific functions with the same name, but the specific implementation methods can be different. For example, shapes include squares, rectangles, circles, etc. Each shape has an area and a circumference, but the method of calculating the area and a circumference for different shapes is different.

Here is an example to illustrate encapsulation, inheritance, and polymorphism:

The base class of this example is the shape mentioned in the description of the concept above. The shape is the base class. This base class is an abstract concept, not a concrete one, so it is an abstract class. This class includes the attribute shape name, the output shape perimeter and area method, and the abstract method for calculating the shape perimeter and area:

  /// <summary>
  /// Shape base class  /// </summary>
  public abstract class Shape
  {
    /// <summary> 
    /// Shape name    /// </summary>
    public string ShapeName { get; private set; }

    public Shape(string shapeName)
    {
      ShapeName = shapeName;
    }

    /// <summary>
    /// Output shape perimeter    /// </summary>
    public virtual void PrintPerimeter(double perimeter)
    {
      (ShapeName + " Perimeter: " + perimeter);
    }

    /// <summary>
    /// Output shape area    /// </summary>
    public virtual void PrintArea(double area)
    {
      (ShapeName + " Area: " + area);
    }

    /// <summary>
    /// Calculate the shape perimeter    /// </summary>
    /// <returns></returns>
    public abstract double CalculatePerimeter();

    /// <summary>
    /// Calculate the shape area    /// </summary>
    /// <returns></returns>
    public abstract double CalculateArea();
  }

Let’s take a look at the specific subclass. The subclass is a circle, which contains the radius of the attribute, the circumference and the area:

  /// <summary>
  /// round  /// </summary>
  public class Circle : Shape
  {
    /// <summary>
    /// The radius of the circle    /// </summary>
    public double R { get; set; }

    public Circle()
      : base("Circle")
    {
       = 0;
    }

    /// <summary>
    /// The circumference of the circle    /// </summary>
    /// <returns></returns>
    public override double CalculatePerimeter()
    {
      return 2 *  * R;
    }

    /// <summary>
    /// The area of ​​the circle    /// </summary>
    /// <returns></returns>
    public override double CalculateArea()
    {
      return  * R * R;
    }
  }

Let’s take a look at the rectangle, which contains the attribute height and width, and how to calculate the perimeter and area:

public class Rectangle : Shape
  {
    /// <summary>
    /// Length of rectangle    /// </summary>
    public double Width { get; set; }

    /// <summary>
    /// The height of the rectangle    /// </summary>
    public double Height { get; set; }

    public Rectangle()
      : base("Rectangle")
    {
      Width = 0;
      Height = 0;
    }

    /// <summary>
    /// The perimeter of the rectangle    /// </summary>
    /// <returns></returns>
    public override double CalculatePerimeter()
    {
      return (Width + Height) * 2;
    }

    /// <summary>
    /// The area of ​​the rectangle    /// </summary>
    /// <returns></returns>
    public override double CalculateArea()
    {
      return Width * Height;
    }
  }

Here is the code called:

Circle circle = new Circle();
 = 20;

Square square = new Square();
 = 10;

Rectangle rectangle = new Rectangle();
 = 20;
 = 30;

// Assigning subclasses to parent classes can better reflect polymorphismIList<Shape> shapeList = new List<Shape>();
(circle);
(square);
(rectangle);

foreach (var shape in shapeList)
{
  (());
  (());
}

In this example, the method of outputting the circumference and area of ​​the shape does not have much effect, because the specific implementation of the method is relatively simple, and it will have great effect if it is a complex method. For example, if you want to implement the drag function, each shape can be dragged, and the method of dragging each shape will be the same, but if you want to implement the drag function, it is not as simple as output. At this time, the subclass can inherit the parent class's methods and call them directly.