5. Inheritance and polymorphism, 5. Inheritance Polymorphism
In this study, we will refer to Andrew Troelsen's C # And. NET4 advanced programming. This section describes the following things: 1. How to Use inheritance to build a set of related classes. 2. How to create a multi-state interface in the class hierarchy using virtual and abstract members. 3. Super parent class System. Object in the. net base class library. The basic Inheritance Mechanism inheritance is one aspect of OOP, which can promote code reuse. More specifically, code reuse is classified into two types, classic inheritance (the "is-a" relationship) and include/delegate model ('has-a' relationship ). Is-a relationship: the is-a relationship between classes, that is, the dependency between two or more class types is created, the basic idea of classic inheritance is that new classes can use the functions of existing classes. Define A base class A as follows: class A {private int num; public int Num {get {return num;} set {num = value ;}} public A () {Console. writeLine (Num);} public A (int aaa) {Console. writeLine ("this is A") ;}1. Specify the parent class of the existing class. If we define A class B to inherit A, it is defined as follows: class B:, class B obtains the public class member Num and public method constructor A () in Class (). (The inheritance class cannot access the Private Members of the parent class, and the inheritance protects the encapsulation.) This achieves code reuse. 2. Multiple Base classes. It is important to remember that C # requires a class to have only one direct base class. We cannot create class types that directly derive from two or more base classes (multiple inheritance ). However, the. net platform allows a class to implement multiple independent interfaces. In this way, the C # type can implement many behaviors while avoiding the complexity caused by multiple inheritance. You can also build flexible interface layers to model complex behavior. 3. sealed keyword. C # provides another keyword sealed to prevent inheritance. If we mark the class as sealed, the compiler will not allow us to derive from this type. For example, we change B to the following form: sealed class B: A {} if class C wants to inherit class B, A compilation error will occur. Class C: B // error. The class marked by sealed cannot be expanded. (The string class is a sealed class and cannot be expanded .) {} Note: the C # structure is always implicitly sealed. Therefore, we can never inherit from the structure, from the class or from the structure. Structures can only be used for modeling independent and user-defined data types. If you want to use the is-a relationship, you must use a class. The second pillar of OOP: inheritance 1. Use the base keyword to control the creation of the base class. In C #, the basic default constructor is automatically called before the constructor of the derived class is executed. To help optimize the creation of a derived class, it is best to implement a subclass constructor to display the call to a suitable custom base class constructor, rather than the default constructor. Class B: A {public B (int a): base (int aaa)} indicates that when we add A custom constructor to the class definition, the default constructor is automatically removed. Therefore, if necessary, we need to redefine the default constructor for the subclass. 2. Family Secrets: the protected keyword. As we know, public items can be directly accessed anywhere, while private items cannot be accessed from other objects except the classes that define them. C # provides another keyword that defines the accessibility of members: protected. When the base class defines protected data or protected members, it creates a set of items that can be accessed by any descendant. If the following definition is added to Class A, Class B can access this information. The benefit of class A {protected int rC;} Is that the derived classes no longer need to use public methods or attributes to indirectly access data. Disadvantage: if a derived class has the right to directly access the internal data of its parent class, it may accidentally bypass the existing business rules set in the public attributes. Finally, it should be noted that the protected data can be considered private for the object users. Therefore, an error occurs if B B = new B (); B. rc = 10. 3. Added sealing class. Sealing classes cannot be extended by other classes. This technology is usually used to design tool classes. If we want to build a new class to use the sealing class function, the only way is to use the include/delegate model (also known as the 'has-a' relationship ). Include/delegate programming we create A class C, and the logic of Class A is represented as class A contains class C. If we update class A, it will be as follows: class A {protected C c = new C () ;}however, if we want to publish the functionality of the contained object to the external world, you need to delegate. To put it simply, a delegate is to add a public member to the include class so that the function of the contained object can be used. For example, class C {public void PrintC () {Console. writeLine ("this is C") ;}} if you want to use the PrintC function of class C, add the following definition class A {public void GetPrintC () {return c. printC () ;}} nested Type Definition: This is another statement of the 'has-a' relationship. In C #, we can define the type (enumeration, class, interface, structure, or delegate) directly in the class or structure scope, the nested type is considered a member of the nested class. The nested type can be used to operate the nested type like other members (Private Members can be accessed ): public Class D {public class C {}// the public nested type can be used by anyone using private class C {}// the private nested type can only be used by members of the included Class .} The third pillar of OOP: C # polymorphism supports the 1, virtual, and override keywords. Polymorphism provides a way for subclasses to define methods defined by the base class. This process is called method rewriting. If the base class wants to define A method that can be rewritten by the subclass, the virtual keyword flag method must be used: partial class A {public virtual void vA (int aaaaa) {// operation logic} if the subclass wants to change the implementation details of the virtual method, the override keyword must be used. Class B: A {public override void vA (int aaaaa) {// operation logic} note that the rewrite method can use the base keyword to freely use the default behavior, in this way, we do not need to completely override the logic for implementing the vA method. Public override void vA (int aaaa) {base. vA (aaaaa); // other processing logic} 2. Seal virtual members. Sealed keyword, which can be used for class types to prevent other types from extending their behavior through inheritance. If we do not want to seal the entire class, but only want to prevent the derived class from rewriting a virtual method, we can add the sealed Keyword: public override sealed void vA (int aaaaa) before the method) {// processing logic} 3. abstract class. Because many base classes are fuzzy entities, a good designer will avoid directly creating base class objects (instances) in the code ). In C #, we can use the abstract keyword to force this programming method. Therefore, we create an abstract base class: abstract partial class {...} at this time, A a = new A (); will produce an error. Although we cannot directly create an abstract class, it is still assembled in memory when it is created. Therefore, it is normal for an abstract class to define several constructors that are called at the time when the derived class is assigned. 4. Build a multi-state interface. If a class is defined as an abstract base class, it can define many abstract members. You can use abstract members when you want to define members that must be implemented in each derived class without providing default implementations. This forces each descendant to have a multi-state interface (different from the interface-defined interface ). In short, the multi-state interface of the abstract base class only refers to a set of virtual or abstract methods. Differences between abstract methods and Virtual Methods: it is not necessary to override virtual methods by subclass, but each subclass is forced to rewrite the abstract methods of the base class. Note: abstract methods can only be defined in abstract classes. If this is not the case, a compilation error occurs. The method for marking abstract is purely xieyi9. It defines the name, return value, and parameter set (not implemented ). 5. Member projection. C # provides a function opposite to method rewriting, where parity is used for projection. Formally, if the defined members of a derived class are the same as those of the base class, the derived class projects the version of the parent class. Compilation generates a warning. The solution is as follows: 1. We can only use the override keyword to update the members of the parent class. 2. We can add the new keyword for the same member of the derived type. In this way, the implementation of the explicit declaration derived type is intentionally designed to hide the version of the parent class. (Equivalent to a member that has no relationship with the parent class) We can also apply the new keyword to any member types inherited from the base class (fields, constants, static methods, attributes, etc ). On the contrary, we need to know that we can still use explicit forced conversions to trigger the implementation of shadow members in the base class. The conversion rules for base classes and derived classes are on the. net platform. The highest base class in the System is System. Object. Therefore, everything is ('is-a') object and can be processed accordingly. Object obj = new A (); the first criterion for forced conversion between types: If two classes are associated through the is-a relationship, it is always safe to save the derived type in the base class reference. (Implicit conversion) The second criterion for forced conversion between types: Use the C # forced conversion operator for explicit downward conversion. (Forced conversion) The as keyword of 1 and C. The as keyword can quickly check whether a type is compatible with another type at runtime. If we use the as keyword, we can check the compatibility by checking the null return value. 2. The is keyword of C. C # language provides the is keyword to check whether two items are compatible. However, unlike the as keyword, if the type is incompatible, the is keyword returns false instead of null reference. Note that we do not need to use the try/catch structure to encapsulate our forced conversion operations, because we know that with such a condition detection, the forced conversion of code in the if region must be safe. Super parent class: System. Object in the. net world, each type will eventually be derived from a base class called System. Object (which can be expressed using the C # keyword object. The Object class defines all types of common members in a framework. If we do not explicitly define the parent class of the class, the compiler will automatically derive our type from the Object. Although its built-in behavior can meet many requirements, it is common for us to rewrite some inheritance methods for custom types: rewrite the ToString () method. Public override string ToString () {} is similar to the method used to override ToString. We can also rewrite the Equals method and the GetHashCode method. Summary This section mainly studies the roles and details of inheritance and polymorphism. In addition, we also studied how to display and convert between the base class type and the derived class type. Finally, we learned some details about the super parent class System. Object, and ended the research on the inheritance, encapsulation, and polymorphism of the three pillars of object-oriented.