Nicky's Blog

学习笔记:接口与抽象类

今天看了android源码的WindowManager相关的代码,想研究下它与Window、windowManagerImpl的关系,一脸懵逼。

抽象类

抽象类是用来描述抽象行为的,比如Animal,我们不知道Animal具体有会有什么样的行为,只有具体的动物类,如Dog,Cat才有具体的行为,才能够被实例化。抽象类是实现多态的一种机制,它可以包含具体方法(有具体实现的方法),也可以包含抽象方法,而继承它的子类必须实现这些方法。

抽象类的特性

  1. 抽象类不能被实例化,但可以有构造函数
  2. 抽象方法必须由子类进行重写
  3. 只要包含一个抽象方法的类,就必须定义为抽象类,不管是否还包含其他方法
  4. 抽象类中可以包含具体的方法,也可以不包含抽象方法
  5. 抽象类可以包含普通成员变量,其访问类型可以任意
  6. 抽象类也可以包含静态成员变量,其访问类型可以任意
  7. 子类中的抽象方法不能与父类的抽象方法同名
  8. abstract不能与private、static、final或native并列修饰同一个方法

接口

“知道这个是做什么的,但是具体不用知道具体怎么做”
“接口是一种规范”

接口在Java当中是通过关键字interface来实现,接口不是类,所以也不能被实例化,接口是用来建立类与类之间的协议,它的提供的只是一种形式,而没有具体的实现。实现类实现(implements)接口,必须实现接口的全部方法
接口是抽象类的延伸,Java不允许多重继承(即不能有多个父类,只能有一个),但可以实现多个接口。


其他解释(转载):

“首先,作为接口定义者来说:定义接口这个动作将会规定一个协议,并可将此协议提供给其他提供者进行实现。
其次,当定义者需要使用接口的实现时,通过使用接口作为引用的类型,可以保证使用相同的方式操作不同的对象而不需要知道正在操作的对象到底是什么。(这就是一种解耦合的方法)
最后,对于接口实现者来说:实现接口这个动作代表保证添加协议中指定的行为和特性到自身中,并允许其他调用者以接口类型的引用的方式操作,并以此实现运行时多态。

作者:Yoto Chang
链接https://www.zhihu.com/question/20111251/answer/109547815


在使用接口的过程中,就注意以下几个问题:

  1. 接口中不能有构造方法。
  2. 接口的所有方法自动被声明为public,而且只能为public,如果使用protected、private,会导致编译错误。
  3. 接口可以定义”成员变量”,而且会自动转为public final static,即常量,而且必须被显式初始化。
  4. 接口中的所有方法都是抽象方法,不能包含实现的方法,也不能包含静态方法
    实现接口的非抽象类必须实现接口的所有方法,而抽象类不需要
    不能使用new来实现化接口,但可以声明一个接口变量,它必须引用一个实现该接口的类的对象,可以使用instanceOf来判断一个类是否实现了某个接口,如if (object instanceOf ClassName){doSth()};
  5. 在实现多接口的时候一定要注意方法名的重复

两者区别

抽象层次不同。可以这样理解,抽象类是对类的抽象,接口是对行为的抽象。抽象类对是类整体进行抽象,包括属性、行为,而接口是对类局部(行为)进行抽象。
跨域不同。抽象类所跨域的是具有相似特点的类,而接口可以跨域不同的类。抽象类所体现的是一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在”is-a” 关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上是一致的, 仅仅是实现了接口定义的契约而已。

WindowManager事项

WindowManagerImpl 实现WindowManager 接口,但外部使用的却是WindowManager 这个对象

1
2
3
4
5
6
7
8
9
10
11
12
13
public class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
private final Context mContext;
private final Window mParentWindow;
......
public static WindowManagerImpl getDefault()
{
return mWindowManager;
}
......
private static WindowManagerImpl mWindowManager = new WindowManagerImpl();
}
1
wm=(WindowManagerImpl)context.getSystemService(Context.WINDOW_SERVICE)

类图参考:

对应着的 WindowManager 接口和 WindowManagerImpl 类就组成了实现部分,所以说这四个类使用的就是典型的桥接模式,Window 中的 addView,removeView 等操作都桥接给了 WindowManagerImpl 去处理。但是实际上 WindowManagerImpl 中并没有去实现 addView 方法,在 WindowManagerImpl 类中持有了一个 WindowManagerGlobal 对象的引用,这个引用是通过单例模式获取的,而 addView 等方法就直接交给了 WindowManagerGlobal 类去处理

其他例子

类似这样的设计还有android的shareprexx和shareprexxxImpl,Editer和EditerImpl
发现android很喜欢这讨论,之前以为context和contextImpl也是,发现这个是继承抽象类


ps:文中部分摘录与下面文章

  1. Java基础篇(一):接口与抽象类
  2. WindowManager解析