接口interface

在面向对象里抽象类说道,如果一个基类全部都抽象了。都没有具体的实现,和接口很像。
但意义上又不是接口。

接口的产生:

  • 自底向上:重构
  • 自顶向下:设计

    抽象类和接口的区别

    首先,只能继承一个基类,可以实现多个接口。

  • 继承是is-a的关系

一个派生类对象可以看成是一个基类对象,也就是说一个派生类对象”是一个”基类对象。一只猫可以说是一只动物,看多态的概念。

  • 接口是has-a的关系

接口更像是功能的集合,是一种约定的功能,但是没有具体实现。子类按照这种约定的功能实现接口。子类有这个功能(has)但是子类不是这个功能(is)

  • 抽象类中的方法不能是private,其他都可以。
  • 接口中的方法肯定是public的,因为是必须的,所以C#干脆禁止你写访问符

    接口是什么?举例

    猫,狗,鱼都是(is)动物,继承动物类。动物共有的特征,吃,睡,动等。猫狗鱼继承了动物,他们也都有吃睡动的特征。 但是猫,狗有(has)[掉毛]这种行为。动物基类没有,不是所有动物都有毛的。比如鱼。 现在写一个掉毛功能的接口,猫狗继承动物类,拥有动物类特征的同时,实现这个掉毛接口,有(has)了掉毛的行为。但猫狗不是(is)掉毛。

其实这种例子是结合现实逻辑来的。写项目往往很多类没有啥现实逻辑。写抽象类抽象方法完全就是基类的方法用不到,干脆不要方法体,写个抽象的,基类全部都抽象了,不如用接口代替算了。
往往软件工程无法和现实映射,但是也要做到面向对象开发,换句话说面向接口也可以。

接口简单实现

  1. //家养动物的功能接口,一般接口用I开头
  2. interface IJiaYangChongWu
  3. {
  4. void DiaoMao();//约定一个掉毛功能
  5. }
  6. abstract public class Animal
  7. {
  8. public abstract void Sleep();
  9. public abstract void Eat();
  10. }
  11. public class Cat : Animal,IJiaYangChongWu
  12. {
  13. //实现接口不用override
  14. public void DiaoMao()
  15. {
  16. Console.WriteLine("猫掉毛");
  17. }
  18. public override void Eat()
  19. {
  20. Console.WriteLine("猫吃鱼");
  21. }
  22. public override void Sleep()
  23. {
  24. Console.WriteLine("猫在猫窝里面睡觉");
  25. }
  26. }
  27. public class Dog : Animal,IJiaYangChongWu
  28. {
  29. public void DiaoMao()
  30. {
  31. Console.WriteLine("狗掉毛");
  32. }
  33. public override void Eat()
  34. {
  35. Console.WriteLine("狗吃肉");
  36. }
  37. public override void Sleep()
  38. {
  39. Console.WriteLine("狗在狗窝睡觉");
  40. }
  41. }
  42. public class Fish : Animal
  43. {
  44. public override void Eat()
  45. {
  46. Console.WriteLine("鱼吃东西");
  47. }
  48. public override void Sleep()
  49. {
  50. Console.WriteLine("鱼在水里睡觉");
  51. }
  52. }

接口隔离原则

实现类不应该依赖它不需要的接口,对接口的依赖应该建立在最小依赖的基础上。

一个接口A,他的实现类W会实现这个接口A的所有功能abcdefg,但是有些功能实现类W并不需要 实现类W只需要abcd功能,而接口A多出了efg功能。 解决办法就是:把接口A拆分成多个小接口,比如接口ABCDEFG,每个接口对应abcdefg功能。实现类W需要abcd功能,就实现ABCD接口,EFG接口不实现。 当另一个实现类需要cdef功能,就实现CDEF接口,其他接口不实现。 这些实现类就没有了他不需要的功能。

  1. namespace ConsoleApp2
  2. {
  3. //交通工具接口
  4. interface IVehicle
  5. {
  6. void Run();
  7. }
  8. //武器接口
  9. interface IWeapon
  10. {
  11. void Fire();
  12. }
  13. //飞行接口
  14. interface IFly
  15. {
  16. void Fly();
  17. }
  18. //坦克接口,实现了交通工具的功能,还实现了武器的功能
  19. interface ITank:IVehicle,IWeapon
  20. {
  21. }
  22. //战斗机接口
  23. interface IFighter : IVehicle, IWeapon, IFly
  24. {
  25. }
  26. //汽车
  27. class Car : IVehicle
  28. {
  29. public void Run()
  30. {
  31. Console.WriteLine("汽车跑");
  32. }
  33. }
  34. //坦克
  35. class Tank : ITank
  36. {
  37. public void Fire()
  38. {
  39. Console.WriteLine("坦克开火");
  40. }
  41. public void Run()
  42. {
  43. Console.WriteLine("坦克跑");
  44. }
  45. }
  46. //战斗机
  47. class Fighter : IFighter
  48. {
  49. public void Fire()
  50. {
  51. Console.WriteLine("飞机开火");
  52. }
  53. public void Fly()
  54. {
  55. Console.WriteLine("飞机飞");
  56. }
  57. public void Run()
  58. {
  59. Console.WriteLine("飞机跑");
  60. }
  61. }
  62. //驾驶人
  63. class Person
  64. {
  65. //只要一个交通工具,不管是车,坦克还是飞机。IVehicle是这些的基接口
  66. private IVehicle vehicle;
  67. public Person(IVehicle vehicle)
  68. {
  69. this.vehicle = vehicle;
  70. }
  71. public void Drive()
  72. {
  73. //我只需要跑的功能
  74. vehicle.Run();
  75. }
  76. public void Attack()
  77. {
  78. //如果要使用Fire,接口就不能是基接口IVehicle了,因为他没有,得是IWeapon
  79. //凡是继承了IWeapon接口的都能用
  80. }
  81. }
  82. }
  1. namespace ConsoleApp2
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. Person p = new Person(new Car());
  8. p.Drive();//car能跑
  9. Person p2 = new Person(new Tank());
  10. p2.Drive();//坦克能跑,因为都继承了IVehicle基接口
  11. }
  12. }
  13. }

接口的显式实现

  1. namespace ConsoleApp2
  2. {
  3. interface IA
  4. {
  5. void A();
  6. }
  7. interface IB
  8. {
  9. void B();
  10. }
  11. class C : IA, IB
  12. {
  13. public void B()
  14. {
  15. Console.WriteLine("BBBB");
  16. }
  17. //这是显式实现,调用C类的A方法时,必须把它当成IA类型的变量
  18. void IA.A()
  19. {
  20. Console.WriteLine("AAAA");
  21. }
  22. }
  23. }
  1. namespace ConsoleApp2
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. C c = new C();
  8. c.B();//这时候只能调用B
  9. IA a = new C();
  10. a.A();//这时候可以调用A
  11. }
  12. }
  13. }