抽象类和接口

来源:互联网 发布:在淘宝上怎么开充值店 编辑:程序博客网 时间:2024/05/17 20:29
学习重点:
  • 抽象类和抽象方法的用法
  • 接口的用法
学习难点:
  • 抽象类和接口的使用场合
  • 面向对象设计原则

1.1初识抽象类和抽象方法
1.1.1区分普通方法和抽象方法
在Java中,当一个类的方法被abstract关键字修饰时,该方法称为抽象方法。抽象方法所在的类必须定义为抽象类。当一个方法被定义为抽象方法后,意味着该方法不会有具体的实现,而是在抽象类的子类中通过方法重写进行实现。
语法:
[访问修饰符] abstract <返回类型> <方法名>([参数列表]);
1.1.2区分普通类和抽象类
在Java中,当一个类被abstract关键字修饰时,该类称为抽象类。
1.1.3定义一个抽象类
当一个类被定义为抽象类时,它可以包含各种类型的成员,包括属性、方法等,其中方法又可以分为普通方法和抽象方法,而普通类不能有抽象方法。
1.2使用抽象类描述抽象的事物
有一个宠物类,宠物具体分为狗狗、企鹅等,那么实例化一个狗狗类,企鹅类时有意义的,而实例化一个宠物类则是不合理的。可以把宠物类定义为一个抽象类,避免宠物类被实例化。
1.3抽象类和抽象方法的优势
抽象类中已经实现的方法可以被其子类使用,使代码可以被复用,同时提供了抽象方法,保证了子类具有自身的独立性。
1.4抽象类的局限性
  • 在有些应用场合,仅仅使用抽象类和抽象方法会有一定的局限性。下面通过"愤怒的小鸟"游戏来进一步分析、认识这种局限性,并学会使用接口改进设计。
  • "愤怒的小鸟"游戏中,分裂鸟和火箭鸟飞出来时是"嗷嗷"叫,但是红色鸟和炸弹鸟飞出来以后,确是"喳喳"叫,胖子鸟出来时干脆不叫。
  • 这时候,使用抽象类就会出现以下问题:第一,叫得方法不再通用,第二,子类继承鸟抽象类之后,写出来的叫得方法可能会出现代码重复的情况,如红色鸟和炸弹鸟都是"喳喳"叫,这时候,就不再符合代码复用的要求。
  • 叫的方法已经不再通用,最自然的想法就是将叫这个方法变为抽象方法,然后由其子类去实现,这样做虽然解决了第一个问题,但是会造成代码冗余的问题,如这里的分裂鸟和火箭鸟中的叫方法也会一样,也就是第二个问题更加突出。要解决上述问题,最理的方式就是使用接口。
1.5初识接口
如果抽象类中所有方法都是抽象方法,就可以使用Java提供的接口来表示。从这个角度来讲,接口可以看作一种特殊的"抽象类"但是采用与抽象类完全不同的语法来表示,两者的设计理念也是不同的。
1.5.1定义和实现一个简单的接口
简单地说,接口是一个不能实例化的类型
语法:
public interface 接口名{
   //接口成员
}
  • 和抽象类不同,定义接口使用interface修饰符,访问修饰只能是public,且可选。
  • 接口成员可以是全局常量和公共的抽象方法。
与抽象类一样,接口要使用也必须通过子类,子类通过implements关键字实现接口。
语法:
public 类名 implements 接口名{
   实现方法
   普通方法
}
  • 实现接口的类必须实现接口中定义的所有抽象方法。接口的实现类允许包含普通方法。
1.5.2更复杂的接口
接口本身也可以继承接口。
语法:
[修饰符] interface 接口名 extends 父接口1,父接口2,……{
     常量定义
     方法定义
}
一个普通类只能继承一个父类,但能同时实现多个接口,也可以同时继承抽象类和实现接口。
语法:
class 类名 extends 父类名 implements 接口1,接口2,……{
    类的成员
}
关于定义和实现接口,需要注意以下几方面的内容:
  • 接口和类、抽象类是一个层次的概念,命名规则相同。
  • 修饰符如果是public,该接口在整个项目中可见。如果省略修饰符,该接口只在当前包可见。
  • 接口中可以定义常量,不能定义变量。接口中的属性都默认用"public static final"修饰。即接口中的属性都是全局静态常量。接口中的常量必须在定义是>指定初始值。
  • 接口中的所有方法都是抽象方法。接口中的方法都默认为public。
  • 和抽象类一样,接口同样不能实例化,接口中不能有构造方法。
  • 接口之间可以通过extends实现继承关系,一个接口可以继承多个接口,但接口不能继承类。
  • 类只能继承一个父类,但可以通过implements实现多个接口。一个类必须实现接口的全部方法,否则必须定义为抽象类。
1.6使用接口的优势
为解决前面的"愤怒的小鸟"设计问题,可以尝试使用接口。
  1. 首先定义一个鸟叫得接口.
  2. 接下来确定接口的实现类,一个"嗷嗷"叫、一个"喳喳"叫的实现类。实际的做法是将各种叫的方式作为接口的实现类。
  3. 然后,在鸟的抽象类中添加一个属性,这个属性就是接口叫的方式的对象,并且实现一个叫得方法,方法的实现就是直接调用接口中叫得方法。
1.7面向对象设计的原则
  • 摘取代码中变化的行为,形成接口
例如,在"愤怒的小鸟"游戏中,鸟叫的行为很大,有的鸟叫,有的鸟不叫,各种鸟叫声一样或者不一样,这种行为最好定义为接口。
  • 多用组合,少用继承
在"愤怒的小鸟"游戏中,通过在抽象鸟中包含鸟叫的属性实现组合,有效地减少了代码冗余。
  • 针对接口编程,不依赖于具体实现
如果对一个类型有依赖,应该尽量依赖接口,尽量少依赖子类。因此子类一旦发生变化,代码变动的可能性大,而接口要稳定的多。在具体的代码实现中,体现在方法参数尽量使用接口,方法的返回值尽量使用接口,属性类型尽量使用接口等。
  • 针对扩展开放,针对改变关闭
如果项目中的需求发生了变化,应该添加一个新的接口或者类,而不要去修改原有的代码。

本章总结
  • 抽象方法使用abstract修饰符,没有方法体。
  • 抽象类使用abstract修饰符,不能实例化。
  • 类只能继承一个父类,但可以实现多个接口。一个类要实现接口的全部方法,否则必须定义为抽象类。Java通过实现多个接口达到多重继承的效果。
  • 接口表示一种约定,也表示一种能力,体现了约定和实现相分离的原则。通过面向接口编程,可以降低代码简的偶合性,提高代码的可扩展性和可维护性。
原创粉丝点击