• 1. 抽象类与接口
  • 2. 抽象类
  • 3. 深入理解抽象类和接口在设计理念上的差别,才能正确选择抽象类或接口来进行开发,本次课程要求大家理解为什么使用抽象类?为什么使用接口?会定义和使用抽象类和接口。
  • 4. 在面向对象的世界里,注满了各种各样的代码。在这个世界里有两个大神,一个叫做抽象类,一个叫做接口。抽象类可以使这个世界的代码很好的复用,每个代码都能在不同的岗位中发挥作用;
  • 5. 比如算数代码,他可以在计算机中工作,也可以在计价器中工作。
  • 6. 接口: 接口可以更好的维护这个世界里的代码,工作环境的变化,不会影响到任何代码的功能。
  • 7. 比如项目工厂中,老厂长代码退休了,新的代码厂长来了,虽然更换了管理者,但是勤劳的工人代码该怎么工作还是怎么工作,财务代码该怎么算账还是怎么算账,也就是说,通过了接口才保证了,厂长的替换没有影响到其他代码的工作,这个就是接口的神奇之处。
  • 8. 正因为有了这两个大神,住在面向对象的额世界里的代码们,才会相互合作的那么和谐。
  • 9. 接下来我们就说一下抽象类和接口。 我们都知道类中都有自己的方法,我们现在看一下普通方法和抽向方法有什么不同. 普通方法需要有访问修饰符、返回类型、方法名、还要有一个方法体。 抽象方法也有访问修饰符、返回类型、方法名、但是它还多一个修饰符------bstract、同时没有方法体,也就是说,抽象方法没有实现。
  • 10. 由此 可以看出,普通方法与抽象方法的区别: 普通方法必须要有实现体 抽象方法不能有实现体,抽象方法要用abstract修饰符来修饰。
  • 11. 接下来我们在看一下普通类与抽象类在相貌上有什么区别: 普通类要有访问修饰符、class关键字和类名,抽象类在普通类的基础上,还多了一个abstract修饰符,这个与抽象方法类似,那么在使用的时候,抽象类与普通类也不一样,普通类可以通过new关键字实例化,而抽象类不能使用new关键字 实例化,这个也是普通类与抽象类的一个关键的区别。
  • 12. 现在我们可以给抽象类一个简单的定义: 简单的说抽象类是一个不能实例化的类,他可以具有抽象方法或者普通方法。 定义抽象类的语法与定义普通类类似,只是多了一个关键字abstract,注意抽象类中可以定义抽象方法,也可以拥有普通方法,而普通类当中只能定义普通方法。
  • 13. 我们来对比一下抽象类与接口,我们已经知道了抽象类用absract修饰符来定义,而且抽象类中可以有抽象方法,也可以有普通方法。 那么接口呢?他是使用interface关键字来定义,关键 字后面是接口名,注意定义接口的时候,不在使用class关键字了。同时,接口中只能拥有抽象方法。
  • 14. 其实从定义就可以看出两个的区别: 接口使用interface声明,抽象类除了抽象方法,还可以有普通方法,而接口中只能有抽象方法,当然两者也是有相同之处,就是抽象类与接口都不能实例化
  • 15. 对比完抽象类与接口,下面我们就来给接口下一个简单的定义: 接口就是一个不能实例化,且只能拥有抽象方法的类型,注意这里说的类型不是类,因为接口不是使用class关键字来定义的,定义接口比较简单了,使用interface关键字来定义接口,同时在强调一下,接口当中只能拥有抽象方法
  • 16. (本页无文本内容)
  • 17. 知道了如何定义了抽象类和接口,接下来我们就说一说,如何使用这两个。 抽象类的使用可以通过继承来实现 ,也就是使用extends关键字,同时,继承了抽象类的子类,必须实现抽象类的抽象方法。
  • 18. 接口的使用,可以通过关键字implements来实现,这个词也是“实现”的意思,同样,实现了接口的类,必须要实现接口中所有的抽象方法,
  • 19. 通过代码如何定义和使用抽象类和接口。 创建和使用抽象类 先定义一个人类
  • 20. 再建一个学生类:
  • 21. 测试类
  • 22. 接口的创建和使用: 创建接口人类接口
  • 23. 接口实现类
  • 24. 测试类:
  • 25. 知道了怎么使用和定义抽象类和接口,在这里在给发大家强调和补充一些内容: 一、抽象类与接口不能实例化 二、抽象类与接口分别被继承与实现的场合,其子类必须实现其中的抽像方法, 以上两点是我们要强调的,最后补充一条抽象类中的抽象方法访问修饰符不能为pivate,接口中的抽象方法访问修饰符必须为public。
  • 26. 填空题:
  • 27. 结果;
  • 28. 到目前为止我们都了解了抽象类与接口这两个的特性。接下来看看为什么使用抽象类与接口,首先要和大家强调一点,接下来的内容一理解为主,应用其次,因为这些内弄是关于面向对象的核心思想的,对于初学者来说能够理解就很不错了,所以大家在学习下面的内容当中,需要紧跟讲解的思路。
  • 29. 现在,我们来看一下为什么使用抽象类。 首先我先说一下大家都玩过游戏,比如愤怒的小鸟,里面有小鸟、猪、猴子等角色的划分,这里我们就以主角小鸟举例子。
  • 30. 当弹弓拉满以后,小鸟就会飞出去,并且每只鸟飞行的轨迹基本适一致的,也就是说小鸟都有飞的行为,并且飞的行为也是一样的,同时发射出来的时候小鸟都会叫,这里我们假设小鸟们的叫声也是一样的,也就是说小鸟们都有叫的行为,并且叫声是一样的。但是每只小鸟的攻击方式不一样,分裂鸟会分裂,火箭鸟的攻击防方式是加速冲撞,也就是说每个鸟虽然都会有攻击行为,但是攻击方式不同。
  • 31. 那么让我们设计这个游戏,我们就可以设计一个抽象类,叫做鸟类,它有两个普通方法,一个飞行,它的实现内容是:弹射-----飞,一个是叫,实现的内容是:嗷……还有一个抽象方法,叫做攻击。 之后我们将火箭鸟,分裂鸟分别设计为一个类,并且继承这个抽象类,以为鸟类抽象类中的飞行方法和叫方法已经实现了,所以火箭鸟,分裂鸟都可以直接使用父类鸟的飞行方法和叫方法,但是攻击方法是抽象方法,也就是说火箭鸟,分裂鸟需要自己实现自己的攻击方法了,火箭鸟的攻击方式是加速冲撞,分裂鸟攻击方式是分裂攻击。这里我们就可以看出来了,火箭鸟、分裂鸟等鸟类都可以继承了抽象类------鸟,各种鸟类的飞行行为一样,所以通过直接使用抽象类中飞行方法,避免在自己的类中再次实现飞行方法,也就是飞行代码能够在任何一个鸟抽象类的子类中复用,同理叫的方法也一样,同时,由于攻击方式不同,每一种鸟类都被要求必须实现自身的攻击行为,这也就保证了每种鸟类的个性。
  • 32. 总而言之,就是抽象类中已经实现的方法可以被其子类使用,使代码可以被复用;同时提供了抽象方法,保证了子类还具有自身的独特性。
  • 33. 在继续讲解之前,偶们先来复习一下多态的内容。多态说白了就是一个子类可有多个不同的样子。 比如:人这个类,它的子类有军人,有警察,那么我们可以说,军人和警察都是人,而且他们都是人的子类,包括其他职业的工作者,也可以概括为人,这中种现象我们就成之为多态 。
  • 34. 那么在代码当中,它主要的表现形式就是,父类或者接口的对象,可以通过父类的子类或者接口的实现类来实例化。以之前讲的人,军人和警察举例,假如person类是一个抽象类,那么Person p = new Person(),这种写法是错误的。假如polices 是人的子类,那么写成Person p = new Police(),就正确了。
  • 35. 为什么这里我们要复习一下多态那,就是因为在演示抽象类的好处时,我们需要用到多态的知识。 下面我们就写一个例子来看一下,使用抽象类的好处。 我们就以愤怒的小鸟为例,我们先创建一个鸟类,在创建鸟的方法。
  • 36. 我们在建一个火箭鸟,叫他继承鸟类,
  • 37. 我们在创建一个分裂鸟,
  • 38. 再创建一个测试类
  • 39. 如果我们发现两只鸟在发射的时候都会叫,叫的声音都是嗷。那应该怎么实现那。首先我们想到在那两种鸟的当中加上叫的方法。 在火箭鸟中加上叫的方法。
  • 40. 在分裂鸟中加上叫的方法,
  • 41. 这样我们这两只鸟都实现了叫的方法了,但是我们发现一个问题,这两个类当中的叫的方法内容一样,也就是方法体重复了,都是输出嗷叫的声音,这样出现了代码溶于的问题了,其实这个方法可以看做 这两个鸟类共有的方法,所以我们抽取出来放到父类 鸟类当中。那我们修改一下 把分裂鸟叫的方法去掉。
  • 42. 修改火箭鸟,把叫的方法删除
  • 43. 在父类鸟类中添加叫的方法,这样子类就可以使用叫的方法了。
  • 44. 我们再到测试类中。进行测试。 这就说明抽象类当中实现一个方法,多个子类都能够使用,代码复用度高。那这就是抽象类的好处。
  • 45. 讲完了抽象类有什么好处,接下来我们再说一下为什么需呀接口。 这里我们还以小鸟为例,通过前面的分析我们明白了一点,抽象类的作用是存放子类中共有的方法,但是如果这个共有的方法不再具有通用性了,该怎么办?
  • 46. 比如这个叫的方法,分裂鸟和火箭鸟飞出来的时候,还是嗷嗷叫,但是 红色鸟和炸弹鸟飞出的时候,却是渣渣叫,胖子鸟出来的时候干脆不叫了,那么在类的关系图中,就可能变成这样的形式。
  • 47. 这个时候,使用抽象类就会出现这么几个问题: 第一,叫的方法不再通用了,也就是在抽象类鸟中实现,已经没有太多的意义了。 第二、子类继承鸟之后,写出来的叫方法可能会出现代码重复的情况,比如红色和炸弹鸟都是渣渣叫,这个时候就不符合代码需要被复用的要求了。
  • 48. 我们一个一个的问题来解决,先看第一个,叫的方法已经不再通用了,第一个方法就是将叫这个方法变为抽象方法,然后由子类去实现,这样做虽然解决了第一个问题,但是会造成代码冗余的问题,向这里的分裂鸟和火箭鸟的叫法也一样,也就是说第二个问题的症状又加剧了,这个时候我们接口就可以派上用场了,我们可以将抽象类中变换的部分提取出来,形成一个接口,这时就涉及到面向对象设计的第一个原则:摘取出代码中变化的行为,形成接口,我们先通过代码来实现一下上序的问题,
  • 49. 优化代码 我们先把叫的方法变成抽象方法,由子类自己去实现
  • 50. 在火箭鸟当中重写叫的方法。
  • 51. 分裂鸟当中重写叫的方法
  • 52. 在创建一个炸弹鸟
  • 53. 我们在创建一个红色鸟
  • 54. 我们在创建一个胖子鸟
  • 55. 通过我们的修改我们发现火箭鸟的叫法和分裂鸟的叫法相同,那么红色鸟的叫法和炸弹鸟的叫法一样,这时候又出现了代码冗余了,,所以我们将叫的方法抽象成抽象方法,使代码更加冗余了,所以说这种优化并不好, 那更好的方法是将这个叫的方法抽象成接口。 我们在父类鸟类中把抽象方法去掉,然后创建一个叫的接口。,
  • 56. 创建一个接口
  • 57. 那么为神魔鸟类里的攻击方法 不用抽象出接口,是因为鸟类攻击方法不同,不会产生代码冗余。如果相同就要抽取成接口。 我们先把代码写到这里,继续往下说,一会在说名为什么抽象出接口。
  • 58. 我们现在说一下如何改进之前的代码,因为有了叫的接口了,接下来就需要确定接口的实现类了,我们是不是在想直接让这几种鸟实现接口呀,但是这样的做法是不是又带来了代码冗余了,而实际的做法是将各种叫的方式作为接口的实现类,而不是各种鸟来做为接口的实现类,在这里大家需要记住一点,接口是针对行为而言的,行为也就是动作。 接下来我们将嗷嗷叫、渣渣叫、不叫、这三种方法作为类来实现接口。之后在抽象类中添加一个属性,这个属性就是接口,叫的方式的对象,并且实现一个叫的方法,方法的实现就是直接调用接口中”叫”的方法。这一步,有体现了面向对象设计的一个原则:多用组合,少用继承。
  • 59. (本页无文本内容)
  • 60. 最后代码改进后就会变成这个样子
  • 61. 之前把叫的方式抽象出来形成接口,体现了面向对象设计的第三个原则:针对接口编程,不依赖于接口实现,之后大家在开发的时候还要注意面向对象的第四个原则:针对扩展开放 ,针对改变关闭,它的意思就是如果项目中的需求发生改变了,应该添加一个新的接口或者类,而不要去修改原有的代码。 我们通过代码看一下优化后会有什么好处。
  • 62. 我们接着上一个例子说: 我们来创建接口的实现类 首先我们创建实现类嗷嗷叫
  • 63. 我们在创建实现类渣渣叫
  • 64. 在创建一个不会叫的
  • 65. 三个实现类就完成了然后我们将叫的接口作为属性放到鸟类当中,这就体现了面向对象当中设计的第一个原则,多用组合,少用继承,
  • 66. 然后通过鸟类的构造方法来实例化接口对象,然后实现叫的方法,方法体的内容就是接口对象的方法。那么这就是面向对象设计的第二个原则:针对接口编程,不已具体实现。
  • 67. 接下来我们来修改鸟类的子类, 因为鸟叫的方法抽象成接口了,所以把原来的重写的叫的方法去掉。然后通过构造方法来实例化接口的对象。调用父类的构造方法,
  • 68. 然后我们修改胖子鸟
  • 69. 再修该改红色鸟
  • 70. 火箭鸟
  • 71. 分裂鸟
  • 72. 修改完了 建一个测试类,测试一下: 先创建三个接口对象,在创建各种鸟类的对象。
  • 73. 连接上面代码
  • 74. 至于为神魔使用接口,我们已经有了一定的了解,简单的说,使用接口就是为了便于代码的维护。接口实现类变化,不会对使用接口的类的产生任何影响,这里我们在总结一下,抽象类和接口的各自作用。抽象类便于复用,接口便于代码维护。
  • 75. 最后我们来总结一下我们讲到内容,首先我们讲了抽象类,抽象类使用abstract修饰符来定义,他可以拥有抽象方法与普通方法,抽象方法不能使用private修饰。
  • 76. 接着我们讲了接口,接口使用interface关键字来定义,接口中只能拥有抽象方法,并且,抽象方法只能使用public来修饰。
  • 77. 使用抽象类和接口的时候需要注意,抽象类与接口不能实例化,继承抽象类或者实现接口的子类,必须实现其中的抽象方法。
  • 78. 抽象类与接口的作用: 抽象类便于复用,接口便于代码维护, 在以后开发中需要大家记住的面向对象设计原则:
  • 79. (本页无文本内容)