当前位置: 主页 > JAVA语言

java泛型逆变与协变-用于泛型中修饰泛型字母的接口和泛型委托能使用

发布时间:2023-06-11 22:15   浏览次数:次   作者:佚名

用于 泛型中修饰泛型字母的,只有泛型接口和泛型委托能使用!!!

协变:out

和谐的变化 , 自然的变化,因为里氏替换原则父类可以装子类,所以子类变父类

逆变:in

逆常规的变化 , 不正常的变化,因为里氏替换原则父类可以装子类但是子类不能装父类,所以父类变子类

完整代码:

using System;
namespace Test
{
	//1.返回值和参数
	//2.用out修饰的泛型,只能作为返回值
	delegate T TestOut<out T>();
	//delegate T TestOut(T t);// 不能作为参数
	//3.用 in 修饰的泛型只能作为参数
	delegate void TestIn<in T>(T t);
	//delegate T TestIn(T t);// 不能作为返回值
	//4.只有泛型接口和泛型委托能使用
	//class Test//错误
	//{
	//
	//}
	//5.结合里氏替换原则理解
	class Father
	{}
	class Son:Father
	{}
	class Program
	{
		public static void Main(string[] args)
		{
			//协变
			TestOut<Son> os = ()=>
			{
				return new Son();
			};
			TestOut<Father> of = os;//协变就是父类泛型委托装载子类泛型委托
			//如果delegate T TestOut();没有out则无法转换,实际返回的是os里的函数返回值为Son
			//逆变
			TestIn<Father> inf = (value)=>
			{
			};
			TestIn<Son> ins =inf;//逆变就是子类泛型委托装载父类泛型委托
			//如果delegate void TestIn(T t);没有in则无法转换,实际返回的是inf里的函数参数为Father value
			Console.ReadKey();
		}
	}
}

协变(covariant)和逆变(contravariant)是指在继承关系中子类的类型如何与父类的类型进行比较。

协变指的是子类可以转换为更通用的父类,即子类的类型参数是父类类型参数的子类型。例如java泛型逆变与协变,一个返回IEnumerable类型的方法可以返回IEnumerable类型,因为string类型是object类型的子类型。在C#中协变用out关键字表示java泛型逆变与协变,只能用于接口和委托的类型参数。

逆变指的是子类可以转换为更特定的父类,即子类的类型参数是父类类型参数的父类型。例如,一个接受IComparer类型参数的方法可以接受IComparer类型,因为object类型是string类型的父类型。在C#中逆变用in关键字表示,只能用于委托的类型参数。

// 协变示例
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // 可以进行协变

// 逆变示例
Comparison<object> comparison = (object1, object2) => 0;
Comparison<string> stringComparison = comparison; // 可以进行逆变

需要注意的是,虽然协变和逆变可以方便地处理一些类似转换的问题,但它们也会导致一些安全隐患和类型不匹配的错误,因此需要仔细考虑使用场景和实际需求。