《Java编程思想》 第九章 接口 记录

  • 接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法。

1. 抽象类和抽象方法

  • 为所有导出类创建一个通用接口唯一理由是,不同的子类可以用不同的方式表示此接口。
  • 我们创建抽象类是希望通过这个通用接口操纵一系列类。
  • Java提供一个叫做抽象方法的机制,这种方法是不完整的;仅有声明而没有方法体。
abstract void f();
  • 包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,该类就必须被限定为抽象的。(否则,编译器就会报错。)
  • 如果从一个抽象类继承,并想创建该新类的对象,那么就必须为基类中的所有抽象方法提供方法定义。如果不这样做(可以选择不做),那么导出类便也是抽象类,且编译器将会强制我们用abstract关键词来限定这个类。
  • 创建抽象类和抽象方法非常有用,因为他们可以是类的抽象性明确起来,并告诉用户和编译器打算怎样来使用它们。抽象类还是很有用的重构工具,因为他们使得我们可以很容易将公共方法沿着继承层次结构向上移动。

2. 接口

  • interface关键词使抽象的概念更向前迈进了一步。abstract关键词允许人们在类中创建一个或多个没有任何定义的方法,提供了接口部分,但是没有提供任何相应的具体实现,这些实现是由此类的继承者创建的。interface这个关键词产生一个完全抽象的类,它根本就没有提供任何具体实现。它允许创建者确定方法名、参数列表和返回类型,但是没有任何方法体。接口只提供了形式,而未提供任何具体实现。
  • interface不仅仅是一个极度抽象的类,因为它允许人们通过创建一个能够向上转型为多种基类的类型,来实现某种类似多重继变种的特性。
  • 一旦实现了某个接口,其实现就变成了一个普通的类,就可以按常规方式扩展它。
  • 可以选择在接口中显式地将方法声明为public的,但即使你不这么做,它们也是public的。因此,当要实现一个接口时,在接口中被定义的方法必须被定义为是public的;否则,它们将只能得到默认的包访问权限,这样在方法被继承的过程中,其可访问权限就被降低了,这是Java编译器所不允许的。

3. 完全解耦

  • 只要一个方法操作的是类而非接口,那么你就只能使用这个类及其子类。如果你想要将这个方法应用于不在此继承结构中的某个类,那么你就会触霉头了。接口可以在很大程度上放宽这种限制,因此,它使得我们可以编写可复用性更好的代码。

4. Java中的多重继承

  • 接口不仅仅只是一种更纯粹形式的抽象类,它的目标比这要高。因为接口是根本没有任何具体实现的,也就是说,没有任何与接口相关的存储;因此,也就无法阻止多个接口的组合。
  • 在导出类中,不强制要求必须有一个抽象的或“具体的”(没有任何抽象方法的)基类。如果要从一个非接口的类继承,那么只能从一个类去继承。其余的基元素都必须是接口。需要将所有的接口名都置于implements关键词之后,用逗号将它们一一隔开。可以继承任意多个接口,并可以向上转型为每个接口,因为每一个接口都是一个独立类型。
  • 当通过这种方式将一个具体类和多个接口组合到一起时,这个具体类必须放在前面,后面跟着的才是接口(否则编译器会报错)。
  • 使用接口的核心原因:为了能够向上转型为多个基类型(以及由此而带来的灵活性)。然后,使用接口的第二个原因却是与使用抽象基类相同:防止客户端程序员创建该类的对象,并确保这仅仅是建立一个接口。这就带来了一个问题:我们应该使用接口还是抽象类?如果要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类。事实上,如果知道某事物应该成为一个基类,那么第一选择应该是使它成为了一个接口。

5. 通过继承来扩展接口

  • 通过继承,可以很容易地在接口中添加新的方法声明,还可以通过继承在新接口中组合数个接口。
  • 在打算组合的不同接口中使用相同的方法名通常会造成代码可读性的混乱,请尽量避免这种情况。

6. 适配接口

  • 接口最吸引人的原因之一就是允许同一个接口具有多个不同的具体实现。在简单的情况中,它的体现形式通常是一个接受接口类型的方法,而该接口的实现和向该方法传递的对象则取决于方法的使用者。
  • 我们可以在任何现有类之上添加新的接口,所以这意味着让方法接受接口类型,是一种让任何类都可以对该方法进行适配的方式。这就是使用接口而不是类的强大之处。

7. 接口中的域

  • 接口中的任何域都自动是static和final的。
  • 既然域是static的,它们就可以在类的第一次被加载时初始化,这发生在任何域首次被访问时。
  • 当然,这些域不是接口的一部分,它们的值被存储在该接口的静态存储区域内。

9. 接口与工厂

  • 接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方法就是工厂方法设计模式。这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个具体实现的对象。理论上,通过这种方法,我们的代码将完全与接口的实现分离,这就使得我们可以透明地将某个实现替换为另一个实现。
  • 如果不使用工厂方法,你的代码就必须在某处指定将要创建的Service的确切类型,以便调用合适的构造器。有了工厂方法,就可以选择一个该工厂实现类,进行初始化。

10. 总结

  • 恰当的原则应该是优先选择类而不是接口。从类开始,如果接口的必需性变得非常明确,那么就进行重构。接口是一种重要的工具,但是它们容易被滥用。
发布了57 篇原创文章 · 获赞 11 · 访问量 9888

猜你喜欢

转载自blog.csdn.net/qq_36160730/article/details/96457612