1. What is polymorphism?
Another important concept in Object-Oriented Programming is polymorphism. At runtime, you can call methods in the derived class by pointing to the base class pointer. You can put a group of objects in an array, and then call their methods. In this case, the effect of polymorphism is shown. These objects do not have to be of the same type. Of course, if they all inherit from a class, you can put these derived classes into an array. If these objects have methods of the same name, you can call the methods of the same name for each object.
The same operation acts on different objects and can have different interpretations to produce different execution results. This is polymorphism. Polymorphism is implemented by using a derived class to overload the virtual function type method in the base class.
In an object-oriented system, polymorphism is a very important concept. It allows customers to operate on an object and complete a series of actions by the object, the system is responsible for explaining the specific action and implementation.
The word "polymorphism" was first used in biology, indicating that organisms of the same race share the same characteristics. In C #, polymorphism is defined as: the same operation acts on instances of different classes. Different classes are interpreted differently and different execution results are generated. C # supports two types of polymorphism:
● Polymorphism during compilation
Polymorphism during compilation is implemented through overloading. For non-Virtual members, during compilation, the system determines the operation based on the passed parameters, returned types, and other information.
● Runtime polymorphism
The running polymorphism is the operation that is performed only when the system is running. In C #, The Runtime polymorphism is implemented by virtual members.
The polymorphism during compilation provides us with a fast running speed, while the polymorphism during runtime brings us a high degree of flexibility and abstraction.
II. Implementation of Polymorphism
Polymorphism is the ability of classes to provide different implementation methods for methods (called with the same name. Polymorphism allows you to call a method of a class without considering the specific implementation provided by the method. For example, a class named road calls the drive method of another class. This other type of car may be sportscar or smallcar, but both provide the drive method. Although the implementation of the drive method varies by class, the road class can still call it, and the results it provides can be used and interpreted by the road class.
Polymorphism in components can be implemented in different ways:
● Interface polymorphism.
● Inheritance polymorphism.
● Polymorphism implemented through abstract classes.
Interface Polymorphism
Multiple classes can implement the same "interface", while a single class can implement one or more interfaces. An interface is essentially a definition of how the class needs to respond. The methods, attributes, and events that the interface description class needs to implement, and the parameter types that each member needs to receive and return, but the specific implementations of these members are left to the implementation class for completion.
One powerful technology in component programming is the ability to implement multiple interfaces on an object. Each interface consists of a small number of closely related methods, attributes, and events. Through the implementation interface, the component can provide functions for any other component that requires this interface, without considering the specific functions contained in it. This allows subsequent component versions to include different functions without interfering with core functions. The component functions most commonly used by other developers are naturally members of the component class. However, components that contain a large number of Members may be difficult to use. Some functions of the component can be considered as separate interfaces implemented in private.
Another benefit of defining features based on interfaces is that you can incrementally add features to components by defining and implementing additional interfaces. Advantages include:
1. the design process is simplified because the components can be very small at the beginning and have the minimum function. Later, the components continue to provide the minimum function while inserting other functions, and determine the appropriate functions by actually using those functions.
2. Simplified compatibility maintenance, because the new version of the component can continue to provide existing interfaces while adding new interfaces. Later versions of client applications can take advantage of these interfaces.
Polymorphism implemented through inheritance
Multiple classes can be "inherited" from a single base class ". Through inheritance, the class receives all methods, attributes, and events of the base class in the same Implementation of the base class. In this way, you can add members as needed, and rewrite the base members to provide different implementations. Note that inheritance classes can also implement interfaces. These two technologies are not mutually exclusive.
C # provide polymorphism through inheritance. For small-scale development tasks, this is a powerful mechanism, but for large-scale systems, it is often proved that there are problems. Over-emphasizing inheritance-driven polymorphism generally results in the large-scale transfer of resources from coding to design, which does not help shorten the overall development time.
When will the inheritance-driven polymorphism be used? Inheritance is first used to add functions to existing base classes. If you start from the fully-debugged base class framework, the programmer's work efficiency will be greatly improved, and the method can be added to the base class without interrupting the version. When an application is designed to contain multiple related classes, and for some common functions, these related classes must share the same implementation, you may also want to use inheritance. The overlapping function can be implemented in the base class, and the classes used in the application can be derived from the base class. Abstract classes merge inheritance and implementation functions, which may be useful when one of the two elements is required.
Polymorphism implemented through abstract classes
Abstract classes provide inheritance and interface elements at the same time. The abstract class itself cannot be instantiated and must be inherited. Some or all members of this class may not be implemented. This implementation is provided by the inherited class. The implemented members can still be overwritten, And the inherited class can still implement additional interfaces or other functions.
Abstract classes provide inheritance and interface implementation functions. Abstract classes cannot be instantiated and must be implemented in the inheritance class. It can contain implemented methods and attributes, but it can also contain unimplemented processes, which must be implemented in the inheritance class. This allows you to provide constant-level functionality in some methods of the class, while enabling options for other processes with flexibility. Another benefit of an abstract class is that when a new version of the component is required, you can add additional methods to the base class as needed, but the interface must remain unchanged.
When to use abstract classes? An abstract class can be used when a group of related components are required to contain a group of methods with the same functions but require flexibility in other method implementations. Abstract classes are also valuable when version issues are expected, because the base classes are flexible and easy to modify.
Example: program implementing Polymorphism
Using system;
Public class drawingbase
{
Public Virtual void draw ()
{
Console. writeline ("I'm just a generic Drawing Object .");
}
}
Public class line: drawingbase
{
Public override void draw ()
{Console. writeline ("I'm a line .");}
}
Public class circle: drawingbase
{
Public override void draw ()
{Console. writeline ("I'm a circle .");}
}
Public class square: drawingbase
{
Public override void draw ()
{Console. writeline ("I'm a square .");}
}
Public class drawdemo
{
Public static int main (string [] ARGs)
{
Drawingbase [] dobj = new drawingbase [4];
Dobj [0] = new line ();
Dobj [1] = new circle ();
Dobj [2] = New Square ();
Dobj [3] = new drawingbase ();
Foreach (drawingbase drawobj in dobj)
Drawobj. Draw ();
Return 0;
}
}
Note: The above program demonstrates the implementation of polymorphism. In the main () method of the drawdemo class, an array is created. The array element is an object of the drawingbase class. The array named dobj is composed of four drawingbase objects. Next, we will initialize the dobj array. Because the line, circle, and square classes are derived classes of the drawingbase class, these classes can be used as the dobj array element type. If C # does not have this function, you must create an array for each class. Inheritance can be used as a base class member to save programming workload. After the array is initialized, execute the foreach loop to find each element in the array. In each loop, each element (object) of the dobj array calls its draw () method. Polymorphism is reflected in: each object's draw () method is called at runtime. Although the referenced object type in the dobj array is drawingbase, this does not affect the virtual method draw () of the drawingbase class that is reloaded by the derived class (). In the dobj array, you can call the overloaded draw () method in the derived class by pointing to the pointer of the drawingbase base class.
The output result is:
I'm a line.
I'm a circle.
I'm a square.
I'm just a generic Drawing Object.
In the drawdemo program, the reload draw () method of each derived class is called. In the last row, the virtual method draw () of the drawingbase class is executed (). This is because the fourth element of the array is the drawingbase class object.
Iii. Virtual Methods
When the virtual modifier is added before the method declaration in the class, we call it a virtual method, and vice versa. Static, abstract, or override repair is not allowed after virtual modifiers are used.
Ornaments.
Example 1: classes with Virtual Methods
Using system;
Public class drawingbase
{
Public Virtual void draw ()
{Console. writeline ("this is a virtual method! ");}
}
Note: The drawingbase class is defined here. This is a base class that can inherit other objects. This class has a method named draw. The draw () method carries a virtual modifier, indicating that the derived class of the base class can overload the method. The draw () method of the drawingbase class completes the following tasks: the output statement "this is a virtual method! "Go to the console.
Example 2: A derived class with an overloaded Method
Using system;
Public class line: drawingbase
{
Public override void draw ()
{Console. writeline ("Draw line .");}
}
Public class circle: drawingbase
{
Public override void draw ()
{Console. writeline ("Circle .");}
}
Public class square: drawingbase
{
Public override void draw ()
{Console. writeline ("draw a square .");}
}
Note: The above program defines three classes. These three classes are derived from the drawingbase class. Each class has a draw () method with the same name, and each of these draw () methods has an overload modifier. The overload modifier allows this method to reload the virtual method of its base class at runtime. The condition for implementing this function is that the class is referenced by pointer variables of the base class type.
For non-Virtual Methods, whether called by the instance of the class or by the instance of the derived class of the class, the method of execution remains unchanged. For a virtual method, its execution method can be changed by the derived class, which is implemented through method overloading.
The following example illustrates the difference between a virtual method and a non-virtual method.
Using system;
Class
{
Public void F () {console. writeline ("a.f ");}
Public Virtual void g () {console. writeline ("A. G ");}
}
Class B:
{
New public void F () {console. writeline ("B. F ");}
Public override void g () {console. writeline ("B .g ");}
}
Class Test
{
Static void main ()
{
B = new B ();
A A = B;
A. F ();
B. F ();
A. G ();
B. G ();
}
}
In this example, Class A provides two methods: Non-virtual F and virtual method G. Class B provides a new non-virtual method F, which overwrites the inherited F. Class B also reloads the inherited method G. The output should be a.f B. f B .g.
Note that in this example, the method. G () actually calls B .g instead of. g. This is because the compile value is A, but the run value is B, so B completes the actual call to the method.
Iv. Interface Polymorphism
Multiple classes can implement the same "interface", while a single class can implement one or more interfaces. An interface is essentially a definition of how the class needs to respond. The methods, attributes, and events to be implemented in the interface description class, and the parameter types that each member needs to receive and return.
The specific implementations of these members are left to the implementation class for completion.
One powerful technology in component programming is the ability to implement multiple interfaces on an object. Each interface consists of a small number of closely related methods, attributes, and events. Through the implementation interface, the component can provide functions for any other component that requires the interface, without considering the specific functions contained in it. This allows subsequent component versions to include different functions without interfering with core functions.
The component functions most commonly used by other developers are naturally members of the component class. However, components that contain a large number of Members may be difficult to use. Some functions of the component can be considered as separate interfaces implemented in private.
Another benefit of defining features based on interfaces is that you can incrementally add features to components by defining and implementing additional interfaces. Advantages include:
● The design process is simplified because the components can be very small at the beginning and have the minimum function. Later, the components continue to provide the minimum function while inserting other functions, and determine the appropriate functions by actually using those functions.
● The compatibility maintenance is simplified, because the new version of the component can continue to provide existing interfaces while adding new interfaces. Later versions of client applications can take advantage of these interfaces (if this makes sense ).
5. Inheritance Polymorphism
Multiple classes can be "inherited" from a single base class ". Through inheritance, the class receives all methods, attributes, and events of the base class in the same Implementation of the base class. In this way, you can add members as needed, and rewrite the base members to provide different implementations. Note that inheritance classes can also implement interfaces. These two technologies are not mutually exclusive.
C # provide polymorphism through inheritance. For small-scale development tasks, this is a powerful mechanism, but for large-scale systems, it is often proved that there are problems. Over-emphasizing inheritance-driven polymorphism generally results in the large-scale transfer of resources from coding to design, which does not help shorten the overall development time. See the following example:
Class B
{Public Virtual void Foo (){}}
Class D: B
{
Public override void Foo (){}
}
// An attempt to reload a non-virtual method will result in a compilation error, unless the "new" keyword is added to the method, // to indicate the method to hide the parent class.
Class N: d
{
Public new void Foo (){}
Public static void main (){
N = new N ();
N. Foo (); // call n's foo
(D) N). Foo (); // call Foo of d
(B) N). Foo (); // call Foo of d
}
}
Compared with C ++ and Java, the override keyword of C # makes it clear to read the source code which methods are overloaded. However, the use of virtual methods has advantages and disadvantages. The first advantage is to avoid using virtual methods to slightly increase the execution speed. The second point is to clearly know which methods will be overloaded.
Let's look at a class about aircraft description. Suppose we have a base class that describes airplanes. Now, we need to complete an aircraft control system with a global function fly, which is responsible for sending the plane to take off. Then, we only need to do this:
Using system;
Class plane
{
Public Virtual void fly () {}// retrieves pure virtual functions
Public Virtual void land () {}// landing pure virtual function
Public Virtual string modal () {}// search for model pure virtual functions
}
// Then, we derive two sub-classes from plane: copter and jet ):
Class copter: Plane
{
Private string fmodal;
Public override void fly (){}
Public override void land (){}
Public override string modal (){}
}
Class jet: Plane
{
Private string fmodal;
Public override void fly (){}
Public override void land (){}
Public override string modal {}
}
This allows all planes that pass on to it (child objects of plane) to take off normally! Whether it's a helicopter, a jet, or even a flying saucer that doesn't exist now, it will be added in the future. Because each subclass has defined its own departure method.
We can see plane. the fly () function accepts the plane Class Object Reference of the parameter, and all the objects actually passed to it are the Child class objects of plane, polymorphism is a technique that allows you to set a parent object to be equal to one or more of its sub-objects, the parent object can operate in different ways based on the features of the sub-objects assigned to it. Apparently, parent = Child; is the essence of polymorphism! Because a helicopter is a plane and a jet is a plane, all operations on the plane can be performed on them. At this time, aircraft is used as an interface. The essence of polymorphism is to assign the pointer of the subclass type to the pointer of the parent class (referenced in OP). As long as such a value is assigned, polymorphism is generated, because "upward ing" is implemented ".
Reprinted: http://hi.baidu.com/ndlli/blog/item/8be807a4e6adb3f49152ee51.html