P28 Abstract Classes and Open-Close Principles

Interfaces and abstract classes are both theoretical and code difficulties.

Interfaces and abstract classes work well, so the code you write tests well.

Introduction

Software is also a branch of the industry, and well-designed software must withstand testing.

Whether the software can be tested, repaired or monitored depends on the use of interfaces and abstract classes.

Interfaces and abstract classes are the cornerstones of modern object-oriented programming and the starting point of higher-order object-oriented programming.

The premise of learning design mode:

  1. Thorough understanding and proficiency with interfaces and abstract classes
  2. Deep understanding of SOLID design principles and conscious use of them in daily work

To do both, you must write down two or three years of code in a team with a quality culture.
It is recommended that you leave the group without quality culture as soon as possible, where you can hardly learn good things and develop a bad habit.

Algorithms, design principles and design patterns must be used in the work to truly master.
Or the sentence "The focus of learning programming is not learning to use".

SOLID

  • SRP: Single Responsibility Principle

  • OCP: Open Closed Principle

  • LSP: Liskov Substitution Principle

  • ISP: InterfaceSegregation Principle

  • DIP: Dependency Inversion Principle

SOLID (Single Function, On/Off Principle, Richter Replacement, Interface Isolation, and Dependency Inversion) is an acronym for the first letter of memory introduced by Robert C. Martin in the early 21st century. It refers to the five basic principles of object-oriented programming and object-oriented design.

Abstract Classes and Open-Close Principles for Base Classes

Abstract classes are closely related to open and close principles.

The importance of design principles and their important role in agile development:

Previously, I learned how to encapsulate and inherit classes. In theory, I like how to use them. But to write high-quality, engineering code, I have to follow certain rules

You have to work with people to write code, even if you write your own stand-alone software, you'll work with them in the future and now

These rules, like traffic rules, were created for efficient collaboration

  1. Hard rules: for example, variable names are legal, syntax is legal

  2. Softness Rules: Programming Principles

abstract class

Once an abstract member is present in a class, it becomes an abstract class and must be marked abstract.

At least one function member within an abstract class is not fully implemented.

	abstract class Student
	{
		abstract public void Study();

	}

An Abstract member is a member that is not yet implemented because it must be implemented in a subclass, so an abstract class cannot be private.

Because there are unimplemented function members inside an abstract class, it has no specific behavior, and the computer does not know how to call such members, the compiler simply does not allow you to instantiate the abstract class.

Instantiation is not allowed for a class; it has only two uses left:

  1. Implement abstract members in a derived class as a base class

  2. Declare base class (abstract class) type variables to refer to instances of the subclass (abstract member in an implemented base class) type, also known as polymorphism.

The implementation of abstract methods looks similar to override override override virtual methods, so they are also called pure virtual methods in some programming languages, such as C++.

There is still a method body for virtual methods, just waiting for subclasses to override abstract, but there is no method at all.

PS: The non-abstract class we learned earlier is also known as the Concrete Class.

Open and Close Principle

If you are not fixing bug s and adding new functionality, don't always modify the class's code, especially the code of its function members.

We should encapsulate those members that are constant, stable, fixed, and deterministic, declare those members that are uncertain and potentially changing as abstract members, and leave them to subclasses for implementation.

Open bug fixes and new features to turn off class changes

Example

The example demonstrates how to add a vehicle class, explaining the open-close principle, Abstract classes, and interfaces through version iteration.

Initial version

From Car direct copy code to Truck:

class Car
{
    public void Run()
    {
        Console.WriteLine("Car is running...");
    }

    public void Stop()
    {
        Console.WriteLine("Stopped!");
    }
}

class Truck
{
    public void Run()
    {
        Console.WriteLine("Truck is running...");
    }

    public void Stop()
    {
        Console.WriteLine("Stopped!");
    }
}

This violates the design principle: you cannot copy paste.

Extract parent version

Extract the same method and place it inside the parent class:

class Vehicle
{
    public void Stop()
    {
        Console.WriteLine("Stopped!");
    }
}

class Car : Vehicle
{
    public void Run()
    {
        Console.WriteLine("Car is running...");
    }
}

class Truck : Vehicle
{
    public void Run()
    {
        Console.WriteLine("Truck is running...");
    }
}

The problem with this is that a Vehicle type variable cannot call the Run method, and there are two solutions:

  1. Add a Run method with parameters inside Vehicle

  2. Virtual method

Add Run with parameters:

class Vehicle
{
    public void Stop()
    {
        Console.WriteLine("Stopped!");
    }

    public void Run(string type)
    {
        if (type == "car")
        {
            Console.WriteLine("Car is running...");
        }
        else if (type == "truck")
        {
            Console.WriteLine("Truck is running...");
        }
    }
}

This violates the open-close principle, adding Run methods without fixing bug s or adding new functionality. And once you add another vehicle class later, you have to open the (Open) Vehicle class and modify the Run method.

Virtual method:

class Program
{
    static void Main(string[] args)
    {
        Vehicle v = new Car();
        v.Run();
        // Car is running...
    }
}

class Vehicle
{
    public void Stop()
    {
        Console.WriteLine("Stopped!");
    }

    public virtual void Run()
    {
        Console.WriteLine("Vehicle is running...");
    }
}

class Car : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("Car is running...");
    }
}

class Truck : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("Truck is running...");
    }
}

The virtual method solves the problem that a Vehicle type variable calls a subclass Run method, but it also leaves a problem: Vehicle's Run method behaves ambiguously in itself and is never called in practice. And from a test point of view, testing a piece of code that you will never use is also unreasonable.

Abstract Class Edition

Otherwise, Run becomes an abstract method by simply writing nothing inside it and then directly drying out the body of Run's method. Vehicle then becomes an abstract class.

abstract class Vehicle
{
    public void Stop()
    {
        Console.WriteLine("Stopped!");
    }

    public abstract void Run();
}

When Vehicle becomes an abstract class, it is easy to add new classes that inherit from Vehicle without modifying Vehicle's code.

abstract class Vehicle
{
    public void Stop()
    {
        Console.WriteLine("Stopped!");
    }

    public abstract void Run();
}

class Car : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("Car is running...");
    }
}
...

class RaceCar : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("Race car is running...");
    }
}

Not only do you have to master the use of the last virtual method, but you also have to understand the problems in the previous process to identify and improve the code in your work.

Pure abstract class edition (interface)

Is it possible that all methods within an abstract class are abstract methods?

VehicleBase is a pure virtual class that pushes down member implementations to Vehicle. After Vehicle implements Stop and Fill, push down the implementation of Run

// Especially Abstract
abstract class VehicleBase
{
    public abstract void Stop();

    public abstract void Fill();

    public abstract void Run();
}

// abstract
abstract class Vehicle:VehicleBase
{
    public override void Stop()
    {
        Console.WriteLine("Stopped!");
    }

    public override void Fill()
    {
        Console.WriteLine("Pay and fill...");
    }
}

// specific
class Car : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("Car is running...");
    }
}

You can see this writing of pure virtual classes in C++, but in C# and Java, pure virtual classes are really interfaces.

  1. Because interface requires all its members to be public, the public is removed

  2. The interface itself contains the meaning "is a pure abstract class" (all members must be abstract), so abstract is also removed.

  3. Because the abstract keyword is removed, the override keyword is also removed from the implementation.

interface VehicleBase
{
    void Stop();

    void Fill();

    void Run();
}

abstract class Vehicle : VehicleBase
{
    public void Stop()
    {
        Console.WriteLine("Stopped!");
    }

    public void Fill()
    {
        Console.WriteLine("Pay and fill...");
    }

    // Run is not implemented yet, so it is abstract
    public abstract void Run();
}

class Car : Vehicle
{
    public override void Run()
    {
        Console.WriteLine("Car is running...");
    }
}

Pure virtual classes have evolved into interfaces, and now the code architecture is a bit like it is used in normal work.

Because the naming convention for interfaces in C#begins with I:

interface IVehicle
{
    void Stop();

    void Fill();

    void Run();
}

summary

 

What are interfaces and abstract classes

  • Interfaces and abstract classes are "software engineering products"

  • Concrete class->abstract class->interface: more and more abstract, less and less internally implemented

  • Abstract classes are classes that do not fully implement logic (they can have fields and non-public members that represent "concrete logic")

  • Abstract classes are created for reuse: they are used exclusively as base classes. Also has decoupling function

    • Details of decoupling are left to the next section on interfaces
  • Encapsulate deterministic, open uncertain (open-close principle), defer to appropriate subclasses

  • Interfaces are "classes" that have no logic at all (pure virtual classes; only function members; all members are public)

  • Interfaces are decoupled: "high cohesion, low coupling" for unit testing

  • The interface is a "contract". Already known to industrial production (division of labor necessitates collaboration, collaboration necessitates agreement)

  • None of them can be instantiated. Can only be used to declare variables and reference instances of concrete class es

For a method, the body of the method is its implementation; For data members, such as fields, it is the implementation of storing data in classes.

Keywords: C#

Added by kybaker on Tue, 08 Mar 2022 19:13:07 +0200