1. 抽象类:分离方法的设计和实现

1.1 目的:

为一类对象建立抽象的模型,在同类对象所对应的类体系中,抽象类往往在顶层。这一方面使类的设计变得清晰,另一方面抽象类也为类的体系提供通用的接口。这些通用的接口反映了一类对象的共同特征。定义了这样的抽象类后,就可以利用Java的多态机制,通过抽象类中的通用接口处理类体系中的所有类。

实际上,即使不包括任何抽象方法,也可以将一个类声明为抽象类。这样的类往往是没有必要定义任何抽象方法,而设计者又 想禁止创建该类的实例变量 ,此时只需要在类的声明中加上abstract关键字。

1.2 注意:

① 定义抽象类和抽象方法可以向用户和编译器明确表明该类的作用和用法,使类体系设计更加清晰,并能够支持多态,因此是Java的一种很有用的面向对象机制。

② 一般将抽象类构造方法的访问权限声明为protected而不是public,从而保证构造方法能够由子类调用而不被其他无关的类调用。

③ 抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。

1.3 抽象方法:

  • 抽象方法不能是静态static方法;
  • abstract不能和final一起出现:
  • abstract修饰的类需要被子类继承,abstract修饰的方法需要子类重写,但是final修饰的类不能被继承,final修饰的方法也不能被子类重写。

  • private不能和abstract同时出现
  • abstract不能用于修饰属性,也不能用于修饰构造器,没有抽象构造器(因为子类也没法重写父类的构造器),抽象类里定义的构造器只能是普通构造器。
  • 1.4 为什么需要抽象类?如何定义抽象类?

  • 是一种 模板模式 。抽象类为所有子类提供了一个通用模板,子类可以在这个模板基础上进行扩展。
  • 通过抽象类,可以 避免子类设计的随意性 。通过抽象类,我们就可以做到严格限制子类的设计,使子类之间更加通用。
  • 1.5 要点:

  • 有抽象方法的类只能定义抽象类;
  • 抽象类不能实例化,及不能用new来实例化抽象类;
  • 抽象类可以包含属性、方法、构造方法。但是构造方法不能用来new实例,只能用来被子类调用;
  • 抽象类只能用来继承;
  • 抽象方法必须被子类实现。
  • 1.6 模板模式的一些简单规则:

    接口作为系统与外界交互的窗口,接口体现的是一种规范。规定了实现者必须向外提供哪些服务;调用者可以调用哪些服务,以及如何调用;当在一个程序中使用接口时,接口是多个模块间的耦合标准;多个应用程序之间使用接口时,接口是多个程序之间通信标准。

    接口类似于整个系统的“总纲”,制定了系统各模块应该遵循的标准,因此一个系统中的接口不应该经常改变。 抽象类作为系统中多个子类的共同父类,它所体现的是一种模板式设计。

    2.2 使用接口的主要优势:

    一是类通过实现多个接口可以实现 多重继承 ,这是接口最重要的作用,也是使用接口最重要的原因——能够使子类对象上溯造型为多个基础类(接口)类型。另一个优势是能够 抽象出不相关类之间的相似性,而没有强行形成类的继承关系 。如果要创建的类体系的基础类不需要定义任何成员变量,并且不需要给出任何方法的完整定义,则应该将基础类定义为接口。只有在必须使用方法定义或成员变量时,才应该考虑采用抽象类。

    由于接口定义的是一种规范,因此接口里不能包含构造器和初始化块定义。接口里可以包含属性(public static final)、方法(public abstract)、内部类(public static)和枚举类定义(public static)。实现方法时,必须使用public修饰符。

    接口不能用于创建实例,但接口可以用于声明引用类型的变量。当使用接口来声明引用类型的变量时,这个引用类型的变量必须引用到其实现类的对象。

    2.3 java 8 接口增加了默认方法和静态方法(只有接口有默认方法)

    默认方法的目的:

    需要修改接口时,不用修改全部的实现类。解决接口的修改和现有的实现不兼容的问题。

    修饰接口方法的修饰符只能是:only public, abstract, default, static and strictfp are permitted

    静态方法:static修饰,接口可声明实现。不可写成抽象方法的形式。

    2.4 接口方法为什么是 public?

    接口是规范,定义公共的行为与状态。实现类不一定在一个包里,不能继承接口,所以也不能是子类,private修饰等于没用。

    2.5 属性变量为什么是 public static final

    public同上。static和final并不用于避免同名,如下。它是在同名的情况下可以通过接口名.变量名区分调用哪个接口下的变量。final:不允许实现类修改(所有类必须遵守)