C#.Net基础加强第四天-接口

接口

  • 什么是接口?
    • 接口就是一种规范,协议(*),约定好遵守某种规范就可以写通用的代码。
    • 定义了一组具有各种功能的方法。(只是一种能力,没有具体实现,像抽象方法一样,“光说不做”)
  • 接口存在的意义:多态。多态的意义:程序可扩展性。最终一让程序变的更灵活,节省成本,提高效率。
  • 接口解决了类的多继承的问题
  • 接口解决了类继承以后体积庞大的问题。
  • 接口之间可以实现多继承
  • 先从语法角度看一下接口,与抽象类类似。

接口的定义和一些概念

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class Program
{
static void Main(string[] args)
{

}
}

//接口不能实例化
//接口就是让子类来实现的。
//1.接口可以实现“多继承”(多实现),一个类只能继承自一个父类,但是可以实现多个接口。
//2.接口解决了不同类型之间的多态问题,比如鱼与船不是同一类型,但是都能在水里“游泳”,
//只是万式不一样,要对游泳”实现多态,就只能考虑接口。

//定义一个接口,建议:一定要以大写 I 开头
public interface IFlyable
{
//接口里面能包含什么成员,接口里面只能包含【方法】,
//(属性,索引器,事件)
//归根结底是只包含 [方法]
//接口中的所有成员,都不能显示的写任何访问修饰符
//默认是pub1ic的访问修饰符

void SayHi();
void M1(string msg);
//在接口中这样写表示是一个未实现的属性。
string Name {
get;
set;
}
//索引器
string this [int index] {
get;
set;
}
}

//接口中的成员,子类必须实现
public class Myclass : IFlyable
{
string name;
public void Sayhi()
{
Console.WriteLine("Hi...");
}
public void M1(string msg)
{
Console.WriteLine(msg + "Hi...");
}
public string Name {
get { return name; }
set { name = value; }
}
public string this[int index] {
get { }
set { }
}
}

两个接口练习

  • 案例(继承了一个类,同时实现了其他接口)
    • 鸟-麻雀 sparrow[‘spereu],鸵鸟 ostrich[ostrit],企鹅penguin[pengwin],鹦鹉parrot[paeret]
    • 鸟能飞,鸵鸟,企鹅不能。。。你怎么办
  • 子类继承抽象类,实现接口
  • 接口中的成员必须不能有实现,接口不能实例化。
  • 接口中的成员不能有访问修饰符,隐式公开public接口中可以有属性、方法、索引器等(其实都是方法),但不能有字段
  • 接口中的所有成员必须被子类中全部实现,除非子类是抽象类,把接口中的成员标记为抽象的。
  • 练习:从学生,老师,校长类中抽象出人的类,学生和老师都有收作业的方法,但是校长不会收作业
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
namespace xueXi_接口
{
class Class1
{
static void Main(string[] args)
{
IFlyable bird = new Parrot()/*Sparrow()*/;
bird.Fly();

}
}
// 鸟
public class Bird
{
public void Brak()
{
Console.WriteLine("叫....");
}
}
public interface IFlyable
{
void Fly();
}
// 麻雀
// 当一个类同时继承父类,并且实现了多个接口的时候,必须将继承类,写在第一个。
public class Sparrow : Bird, IFlyable
{
public void Fly()
{
Console.WriteLine("麻雀飞...");
}
}
// 鸵鸟
public class Ostrich : Bird
{
}
// 企鹅
public class Penguin: Bird
{
}
// 鹦鹉
public class Parrot : Bird, IFlyable
{
public void Fly()
{
Console.WriteLine("鹦鹉飞...");
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
namespace xueXi_接口
{
class Class2
{
static void Main()
{
ICollectHomework person = new Teacher()/*Student()*/;
person.Collect();
}
}

public interface ICollectHomework
{
void Collect();
}

public class Person
{

}
public class Student : Person, ICollectHomework
{
public void Collect()
{
Console.WriteLine("学生收作业...");
}
}
public class Teacher : Person, ICollectHomework
{
public void Collect()
{
Console.WriteLine("老师收作业...");
}
}
public class SchoolMaster : Person { }
}

再看一个接口案例

  • 回顾:接口是一种规范。
    • 什么是规范?理解规范的意义。规范,就是告诉我们要做什么,具有什么能力。
    • 在程序中为什么需要规范?(多态,可以让我们编写通用的代码,提高程序的可扩展性)
    • 接口就像“法律”。
  • 登记方法(接口作为参数,实现多态)
    • DengJi(Person person)//人口登记,Person是抽象类
    • DengJi(Car car)//汽车也要登记
    • DengJi(House house)//房子也要登记.JiKou
    • DengJi(lJieKou jk);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
namespace xuexi_接口练习
{
class Program
{
static void Main(string[] args)
{
German g = new German();
Car car = new Car();

Dengji(g);
Dengji(car);
}

public static void Dengji(IShowInfo dengji)
{
dengji.show();
}
}

public interface IShowInfo
{
void show();
}
class Chinese { }
class Americn { }
class German : IShowInfo
{
public void show()
{
Console.WriteLine("德国人....");
}
}
class Car : IShowInfo
{
public void show()
{
Console.WriteLine("兰博基尼...");
}
}
}

显示接口

  • 为什么要显示实现接口?
    • 方法重名后的解决办法。
  • 显示实现接口后,只能通过接口来调用。不能通过类对象本身来调用(显示实现的接口,查看ILprivate的,防止通过类来调用
  • 为什么要有“显示实现接口”?
    • 可以解决重名方法的问题。T
  • 什么是“显示实现接口”?
    • 实现接口中的方法时用:接口名.方法名(),并且没有访间修饰符,private
  • “显示实现接口”后怎么调用?
    • 只能通过接口变量来调用,因为显示实现接口默认为private
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

namespace xuexi_显示接口
{
class Program
{
static void Main(string[] args)
{
IFace1 stu = new Student();
stu.Fly();
IFace2 stu1 = new Student();
stu1.Fly();

IFace1 stu3 = new Teacher();
stu3.Fly();
IFace2 stu4 = new Teacher();
stu4.Fly();
}
}

interface IFace1
{
void Fly();
}
interface IFace2
{
void Fly();
}

class Student : IFace1, IFace2
{
public void Fly()
{
Console.WriteLine("Iface1");
}
}

internal class Teacher : IFace1, IFace2
{
public void Fly()
{
Console.WriteLine("1");
}

void IFace2.Fly() // 只能私有,通接口调用
{
Console.WriteLine("2");
}
}
}

接口的总结

  1. 接口是一种规范。为了多态。
  2. 接口不能被实例化。
  3. 接口中的成员不能加“访问修饰符”,接口中的成员访问修饰符为public,不能修改。(默认为public
  4. 接口中的成员不能有任何实现(“光说不做”,只是定义了一组未实现的成员)
  5. 接口中只能有方法、属性、索引器、事件,不能有“字段”
  6. 接口与接口之间可以继承,并且可以多继承。
  7. 实现接口的子类必须实现该接口的全部成员。
  8. 一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,那么语法上A必须写在IA的前面。class MyClass:A, IA {},因为类是单继承的。
  9. 当一个抽象类实现接口的时候,如果不想把接口中的成员实现,可以把该成员实现为abstract。(抽象类也能实现接口,用abstrac标记)
  10. “显示实现接口”,只能通过接口变量来调用(因为显示实现接口后成员为private)。

使用接口的建议

  • 面向抽象编程,使用抽象(父类、抽象类、接口)不使用具体。
  • “向上转型”
  • 在编程时:
    • 接口 -> 抽象类 -> 父类 -> 具体类(在定义方法参数、返回值、声明变量的时候能用抽象就不要用具体。)
    • 能使用接口就不用抽象类,能使用抽象类就不用类,能用父类就不用子类。
    • 避免定义“体积庞大的接口”、“多功能接口”,会造成“接口污染”。只把相关联的一组成员定义到一个接口中(尽量在接口中少定义成员)。单一职责原则
    • 定义多个职责单一的接口(小接口)(组合使用)。(印刷术与活字印刷术)
  • 随着学习的深入再继续体会接口的作用。

抽象类复习、简单工厂设计模式复习

  • 抽像类:
    • 不能被实例化,需要被继承。多态。
    • 子类必须重写父类中的所有的抽象成员,除非:子类也是一个抽象类。
    • 抽象成员在父类中不能有任何实现。
    • 抽象类中可以有实例成员。
    • 抽象成员的访问修饰符不能是private
    • 抽象成员只能写在抽象类中。
    • abstract
  • 作业:通过案例笔记本电脑的选择。
    • 笔记本电脑父类NoteBook、不同品牌的笔记本产品。(继承+简单工厂)

接口复习

  • 定义接口的语法(interface
    • 接口中只能包含方法、属性、索引器、事件。不能包含字段。见备注1(貌似事件像一个字段?其实是两个方法。reflector查看源码)
    • 接口中的成员不能有任何的实现(真正的“光说不做”。思考这样做的意义。联想抽象类中的抽象方法。)
    • 接口中的成员不能写访间修饰符。
  • 使用接口的语法
    • 一个类可以实现多个接口。
    • 实现接口的类,必须把接口中的所有成员都实现。
    • 子类实现接口中的成员时,不能修改成员的访间修饰符、参数列表、方法名等。(与方法重写一样)

面试题

  1. 如何使用virtualoverride
    • Person per = new Student();
    • per.SasHI()调用的子类重写的SayHi方法(语法、应用(多态))
  2. 如何使用abstractoverride
  3. “方法重载overload”、“方法重写override”、”隐藏new”是同一个概念吗?
  4. 抽象类和接口的区别?见备注1.
    • 抽象类适用于同一系列,并且有需要继承的成员。
    • 接口适用于不同系列的类具有相同的动作(行为、动作、方法)。
    • 对于不是相同的系列,但具有相同的行为,这个就考虑使用接口。
    • 接口解决了类不能多继承问题。

virtual: 是用来标记虚方法的。
override: 是进行方法重写的,当子类继承父类的时候重写父类的方法。




参考:
1.link-01 // B站 -> C#.Net基础加强第四天-接口与异常处理 -> 传智播客

感谢支持!