C# 接口与泛型

接口

  刚学完继承,得知继承用于创建可重用,扩展和修改在其他类中定义的行为的新类。但是我们发现继承只能单继承,生活中我们会发现不是所有的事物都具有该类事物普遍的功能,比如,喜鹊鹦鹉会飞,但鸵鸟企鹅不会飞。这时候继承虽然可以解决这类问题,但不是最好的,我们通过另一种方式能够跟好的解决上述问题,那就是接口。
  接口和类是同级的,TA和类非常相似,所以TA也是应用类型。
  使用接口有几个注意点:
  1.接口的关键字是interface,通常所有的接口以大写I开头后面使用驼峰法
  2.接口中的方法是不实现的,接口中的方法都是public,我们不能去使用访问修饰符,接口中不能包含字段
  3.当一个类继承了接口,那么这个类必须实现接口中的所有方法,除非继承的类是一个抽象类或还是一个接口
  我们先随意定义两个接口:

interface IFly
{
    void Fly();
}

interface ISpeak
{
    void Speak();
}

  当一个接口继承多个接口之后,那么这个接口相当于拥有了TA所有继承的方法声明。如果某个类继承了这个接口,那么TA不仅仅要实现这个接口中的内容,也要实现这个接口所继承的接口中的内容。接口和继承相似,也是写在类名后面,接口与接口之间以逗号隔开。如果这个类有继承,那么接口必须写在基类的后面,因为基类只有一个,而接口可以有多个。例如:

interface IKun : IFly, ISpeak
{
	void AiKunKun();
}
class Bird : IKun
{
	public void AiKunKun()
	{
    	throw new NotImplementedException();//自动补齐的方法,自行重写
	}

	public void Fly()
	{
    	Console.WriteLine("我会飞");
	}

	public void Speak()
	{
    	Console.WriteLine("我会说话");
	}
}

接口总结

接口的特性:
1.接口是一个引用类型,只包含了功能的定义,不包含功能的实现
2.C#接口成员的访问级别是默认的(默认为public),不可以使用其他修饰词修饰
3.C#接口成员不能有static,abstract,override,virtual修饰
4.接口一旦被实现,就必须实现接口当中的所有成员,除非实现类本身是抽象类
5.接口无法直接进行实例化,因为其成员必须通过由实现接口的任何类或结构来实现
6.接口可以包含事件,索引器,方法和属性,但是不能包含字段
7.类的继承只能单继承,接口的实现支持多实现
8.接口中方法的定义不允许加上访问修饰符,默认修饰符为public
9.类实现接口就必须实现接口当中定义的所有方法,除非该类是抽象类

接口与抽象类的区别

接口与抽象类非常相似,它们之间有共同点:
1.两者都不能被实例化
2.两者都包含了由其他类或结构继承或实现的抽象成员
也有不同点:
1.抽象类当中除了拥有抽象成员外还可以拥有非抽象成员;而接口中所有的所有成员都是抽象的
2.抽象成员可以使用修饰符修饰,接口当中接口成员访问级别是默认不可修改的,并且默认是public
3.接口当中不可以包含构造方法,析构方法,静态成员以及常量
4.C#类只支持单继承,接口支持多支持

泛型

  我们在编写程序的时候经常会遇到两个模块的功能非常相似,只是因为参数类型不同,所以分写成多个方法处理每种数据类型。例如:

public void Add(int a, int b)
{
	Console.WriteLine(a + b);
}
public void Add(double a, double b)
{
	Console.WriteLine(a + b);
}
public void Add(string a, string b)
{
    Console.WriteLine(a + b);
}
//我们可以采用根类Object,来解决这个问题
public void NewAdd(object a, object b)
{
    Console.WriteLine(a.ToString() + b.ToString());
}

  object可以是任意类型,根据我们所写的参数不同,TA会自动识别类型,但是有缺陷,会有装箱和拆箱的操作,对性能造成非常大的影响。因此我们引入了泛型,在方法的后面加一个类似参数的(类型参数),这个参数代表我们在使用的时候填写什么类型,TA就是什么类型。

public void Swap<T>(ref T a, ref T b)//T代表类型占位符
{
    T temp = a;
    a = b;
    b = temp;
}
//一个方法可以有多个泛型类型的参数
public void Print<T, V>(T a, V b)
{
    Console.WriteLine(a);
    Console.WriteLine(b);
}

泛型的优点:
1.使用泛型可以的重用代码,保护类型的安全以及提高性能
2.降低强制转换或装箱操作的成本和风险
3.可以对泛型参数进行限定以访问特定数据类型的方法

泛型类型参数

  在泛型类型或方法定义中,类型参数是客户端在实例化泛型类型的变量时指定的特定类型的占位符。在上面例子泛型方法当中T即为泛型类型参数。
泛型类型参数注意点:
1.泛型类型参数可以有多个
2.泛型类型参数可以是编译器识别的任何数据类型
3.泛型类型参数命名需要遵守命名规则
  (1)使用描述性名称命名泛型类型,并且使用T作为前缀
  (2)单个字母名称完全可以让人了解其表示的含义使用单个大写字母命名
泛型类型参数常用的约束类型
where T:struct :表示泛型T是值类型(小数,整数,char,bool,struct)
where T:class :表示泛型T是引用类型
where T:new() :表示这个泛型具有一个无参数的构造方法,如果有多个约束,new()必须放在最后
where T:基类名 :表示这个泛型是该基类或者其派生类
where T:接口名 :表示泛型是实现了该接口的类型
注意:指定泛型类型T必须是一个值类型,不能同时添加struct和class约束

public void Add2<T>(T a, T b) where T : struct
{
    Console.WriteLine(a.ToString() + b.ToString());
}

泛型方法

格式: 访问修饰符 返回值类型 方法名<泛型类型参数>(参数列表)
   {
     方法体
   }
调用泛型方法:对象/类.方法名<具体类型>(实参)

泛型类

泛型类封装了不是特定于具体数据类型的操作,当类中存在未知参数类型的时候就可以使用泛型类
格式:
修饰符 class 类名<泛型类型参数>
{

  类成员
}

例如:

class Student<T, V> 
{
     public void Study(T a)
     {
         Console.WriteLine(a);
     }

     public void Eat(T a, V b)
     {
         Console.WriteLine(a.ToString() + b.ToString());
     }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值