The coordination and inverter should start with Object-oriented Inheritance. The inheritance relationship refers to the relationship between the Child class and the parent class. The Child class inherits from the parent class, so the child class instance is also the parent class instance. For example, Animal is a parent class, and Dog is a subclass inherited from Animal. If an object type is Dog, it must be Animal.
The Inter-variant inversion is a transformation between the delegate or generic interfaces of different parameter types or return value types using inheritance relationships. I admit that this sentence is very difficult, if you also think that you may wish to look down.
If a method accepts the Dog parameter, the other method that accepts the Animal parameter can certainly accept the parameter of this method. This is the inversion of Animal to Dog. If the returned value of a method is Animal, the method that returns Dog must meet the returned value. This is a covariant of the Dog-to-Animal direction.
Changing from a subclass to a parent class is an out keyword used for the return value type.
The conversion from the parent class to the subclass is the in keyword used by the inverter for the parameter type of the method.
The Coordination inversion in the covariance inversion is relative to the direction of the inheritance link.
I. array covariant:
Animal [] animalArray = new Dog [] {};
The above line of code is valid. The declared array data type is Animal, but the Dog array is actually assigned when the value is assigned. Every Dog object can be safely converted to Animal. The transformation from Dog to Animal method changes upwards along the inheritance chain, so it is a covariant.
Ii. Coordination and inverter in Delegation
1. covariant in Delegation
// The Return Value of the delegate definition is Animal type and parent class
Public delegate Animal GetAnimal ();
// The Return Value in the delegate method implementation is Dog, which is a subclass.
Static Dog GetDog () {return new Dog ();}
// The returned value of GetDog is Dog, and Dog is a subclass of Animal. Returning a Dog is definitely equivalent to returning an Animal. Therefore, the value assigned to the delegate is valid.
GetAnimal getMethod = GetDog;
2. Inverter in Delegation
// Set the parameter type in the delegate to Dog.
Public delegate void FeedDog (Dog target );
// The parameter type in the actual method is Animal
Static void FeedAnimal (Animal target ){}
// FeedAnimal is an effective method for FeedDog delegation, because the parameter type accepted by the delegation is Dog, while FeedAnimal accepts animal and Dog can be implicitly converted to Animal, therefore, the delegate can perform type conversion securely and correctly execute the delegate method;
FeedDog feedDogMethod = FeedAnimal;
The parameter used to define the delegate is a subclass. In fact, the delegate method parameter is a broader parent class Animal. It is a transformation from the parent class to the subclass, and is an inverter.
Iii. Coordination and inverter of generic delegation:
1. Inverter in generic delegation
The following Commission statement:
Public delegate void Feed <in T> (T target );
The Feed delegate accepts a generic type T. Note that there is an in keyword in the angle brackets of the generic type. This keyword is used to tell the compiler that the type T may be used for inverter when assigning values to the delegate.
// Declare a delegate whose T is Animal first
Feed <Animal> feedAnimalMethod = a => Console. WriteLine ("Feed animal lambda ");
// Assign the T-Animal Delegate to the T-Dog delegate variable. This is legal because the in keyword is used when defining the generic delegate. if you remove the in keyword, the compiler considers it invalid.
Feed <Dog> feedDogMethod = feedAnimalMethod;
2. covariant in generic delegation
The following Commission statement:
Public delegate T Find <out T> ();
The Find delegate returns an instance of the generic type T. There is an out keyword in the angle brackets of the generic type. This keyword indicates that the T type may be subject to covariant.
// Declare the Find <Dog> delegate
Find <Dog> findDog = () => new Dog ();
// Declare the Find <Animal> delegate and assign the findDog value to findAnimal. Changing the type T from Dog to Animal is a covariant.
Find <Animal> findAnimal = findDog;
Iv. Coordination and inverter in generic interfaces:
The covariant inversion in the generic interface is very similar to that in the generic delegate, but the angle brackets of the generic definition are changed to the interface definition.
1. Inverter in generic Interfaces
The following interface definition:
Public interface IFeedable <in T>
{
Void Feed (T t );
}
An in keyword exists before the interface generic T to indicate that this generic interface may be subject to an inverter.
The following generic type FeedImp <T> is used to implement the above generic interface. Note that the co-variant and inverter keywords in cannot be used in generic classes, the compiler does not allow
Public class FeedImp <T>: IFeedable <T>
{
Public void Feed (T t ){
Console. WriteLine ("Feed Animal ");
}
}
Let's look at an example of using the interface inverter:
IFeedable <Dog> feedDog = new FeedImp <Animal> ();
The above Code assigns the FeedImp <Animal> type to the IFeedable <Dog> variable. Animal changes to Dog, so it is an inverter.
2. covariant in generic Interfaces
The following interface definition:
Public interface IFinder <out T>
{
T Find ();
}
The out keyword is used before the generic T of a generic interface to indicate that this interface may be subject to covariant. the following generic interface implementation class
Public class Finder <T>: IFinder <T> where T: new ()
{
Public T Find (){
Return new T ();
}
}
// Use covariant. The generic type of IFinder is Animal. However, due to the out keyword, I can assign the Finder <Dog> to it.
IFinder <Animal> finder = new Finder <Dog> ();
The concept of covariant and inverter is not easy to understand, and can be understood through actual code thinking. Is it useful for such a wrap? The answer is yes. Code can be reused through covariant and inverter. Reuse is an eternal pursuit of software development.
--------------------------------------------------------------------------------
Please respect the work of the author, repost please keep the link to yukai technical blog