接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法。
包含抽象方法的类,就是抽象类,抽象类不可以产生实例,但是不能继承。
抽象类往往作为一个基类,用于扩展和多态。
abstract class Test1 {
abstract void foo();
}
抽象类里面的abstract方法,是不需要实现的。
抽象方法的权限 可以是public protect 或者包访问,不可以是私有的。
派生类,要实现所有抽象方法,不然也是抽象类。
抽象类里面还是很灵活的,可以定义和实现普通的方法和成员变量。
成员变量不可以是抽象的。
抽象方法不可以是静态或者final的。
总的来说,就是基类的抽象方法不带方法体,就是为了让派生类来实现这些方法,当然不会是static,final、private的。
接口是一种比抽象类更抽象的方式。
interface Game {
void play();
}
class MyGame implements Game {
public void play(){
System.out.println("play fun");
}
}
用interface关键字产生接口,接口里面不可以有方法体,所有方法都是public,如果里面有成员变量,都是public static final的变量。
也就是策略模式、适配器模式。
有一个类A,有3种实现A1,A2,A3;用一个静态方法apply参数为 A的对象,内部使用这个对象进行操作,这样就可以更具传参的不同改变策略。 这就是策略模式。
class A {
void process(Object sth){
}
}
class A1 extends A {
}
class A2 extends A {
}
class A3 extends A {
}
class Test {
public static void apply(A ob,Object sth){
ob.process(sth)
}
}
但是如果出现另外一个接口C,有实现C1,C2,C3。可能我们又要编写一个静态方法D来处理,是否可以复用方法B呢。
方法1:
要分两步,第一步把A改成一个接口,那么apply方法的参数只需要是一个接口A,只要让C1,C2,C3也去实现接口A,或者把C改成一个实现接口C的抽象类,那么C1,C2,C3都是一个A。
方法2: 如果不能去修改C,C1,C2,C3. 这些我们创造一个适配器。
适配器adapter,本来来实现接口A,并代理C(当然也可以继承,不过这里继承不适合C1,C2,C3),就是process方法代理的是C中的process。
class AdapterC implements A {
private C c;
AdapterC(C c){
this.c = c
}
XType process(Object sth){
c.process(sth);
}
}
apply方法,接受适配器adapter为参数即可。内部的问题都由适配器解决。
由于java是单根的,接口可以实现多重继承。
interface B {
}
interface C {
}
class A implement B,C {
}
建议继承多个接口时,方法名称应该不同,不然会造成混乱。
接口之间可以继承,并且一个接口可以继承多个接口。
interface A {
}
interface B {
}
interface C extends A,B {
}
这是一个有点混乱的玩法,
这个可能只是为了语法的完备性,搞出来的用法。
我们梳理一下,
情况1 . 如果class里面有interface。
我们显然可以在内部实现这个接口,那这个class的派生类,是否需要实现这个接口,是否可以实现这个接口。
我感觉,是不需要实现,但是可以实现,但是如果是private的肯定实现不了。
class Exp1_1 {
interface A {
}
private interface B {
}
}
class Exp1_2 extends Exp1_1 {
class Exp1_2_1 implements A {
}
// class Exp1_2_2 implements B {}
}
一次可以推断一些类似的问题,
1. 接口本身的权限就像普通成员方法一样。
2. 实现类或者派生类是可以选择是否要实现嵌套接口。
如果一个公开的方法f,返回类型是一个私有的接口D(就算实际返回是一个公开实现),这个方法f的结果,是无法直接使用的。
只能找另外一个方法,它的参数是私有接口D,直接使用这个返回值。
这个就略吧,比较简单
按照书中的描述,使用接口的核心原因:
那么什么时候用接口,需要不带方法体和变量的基类,应该用接口。
那么我们再看看区别,