Java中的接口

六. 接口

特性1 - 解决单继承

语法如下

interface A {
    public default void a() {}
}

interface B {
    public default void b() {}
}

// C 从 A, B 两个接口重用方法 a() 和 b()
class C implements A, B {
    
}

解决之前的问题

public class TestInterface1 {
    public static void main(String[] args) {
        Duck d = new Duck();
        d.swim();
        d.fly();
    }
}

interface Swimmable {
    default void swim() {
        System.out.println("游泳");
    }
}

interface Flyable {
    default void fly() {
        System.out.println("飞翔");
    }
}

class Duck implements Swimmable, Flyable {

}
  • 需要放入接口的方法, 必须加 default 关键字(默认方法)
  • default 方法只能是 public, public 可以省略

特性2 - 接口多态

  1. 用父类型代表子类对象,或者用接口类型来代表实现类对象
  2. 必须发生方法重写
«interface»
E
void e()
F
void e()
G
void e()

看这张图,上面这是接口E,下面这俩类 F、G 实现了接口,他俩以后可以叫做实现类,看一下这种上下级关系就可以知道,它们之间符合向上转型,F,G能够沿箭头向上转换为接口类型,因此能用接口类型代表实现类对象

先来看第一条,接口类型可以代表实现类对象

public class TestInterface2 {
    public static void main(String[] args) {
        E[] array = new E[] {
                new F(),
                new G()
        };
    }
}
interface E {
}
class F implements E {
}
class G implements E {
}

再看第二条,方法重写

public class TestInterface2 {
    public static void main(String[] args) {
        E[] array = new E[] {
                new F(),
                new G()
        };
        for (int i = 0; i < array.length; i++) {
            E e = array[i];
            e.e(); // 多态
        }
    }
}
interface E {
    default void e() { 
        System.out.println("e");
    }
}
class F implements E {
    @Override
    public void e() { 
        System.out.println("f");
    }
}
class G implements E {
    @Override
    public void e() {
        System.out.println("g");
    }
}
  • 要注意:方法重写时,要求:子类和实现类 方法访问修饰符 >= 父类和接口 方法访问修饰符
  • default 方法的访问修饰符其实是省略了 public,实现类中方法的访问修饰符要 >= public 才不会出错
  • 多态性:
    • 表面调用的是接口的 E.e() 方法
    • 实际会根据 e 的实际类型调用重写方法,即 F.e() 和 G.e() 方法

抽象方法

其实要使用接口多态,更多地是使用一种抽象方法,而非默认方法,所谓抽象方法仅有方法声明,没有方法体代码。

它包含 abstract 关键字,而且也只能是 public 的,平时这俩关键字都可以省略不写

public class TestInterface2 {
    public static void main(String[] args) {
        E[] array = new E[] {
                new F(),
                new G()
        };
        for (int i = 0; i < array.length; i++) {
            E e = array[i];
            e.e(); // 多态
        }
    }
}
interface E {
    void e(); // 抽象方法,没有方法体,只能是 public 的,省略了 public abstract
}
class F implements E {
    @Override
    public void e() { // 默认
        System.out.println("f");
    }
}
class G implements E {
    @Override
    public void e() {
        System.out.println("g");
    }
}

为啥抽象方法设计为不需要方法体呢?因为你看:

  • 反正多态要求实现类发生方法重写,既然方法重写了,就调用不到接口方法的代码了
  • 既然多态发生时,用不到接口中可能的代码,还不如让方法体空着

另外,抽象方法有个好处:它强制了实现类要实施方法重写,如果实现类没有重写,语法上会报错

特性3 - 接口封装

接口封装的更为彻底

public class TestInterface3 {
    public static void main(String[] args) {
        M m = new N(); // 用接口类型代表了实现类对象
        m.m(); // 只能调用接口中定义的方法
    }
}

interface M {
    void m(); // public abstract
}

class N implements M {
    public String name;

    @Override
    public void m() {
        System.out.println("m");
    }

    public void n() {
        System.out.println("n");
    }
}
  • 只能调用到接口中的方法,对实现类中的其它方法,一无所知
  • 接口限制了只能通过方法来使用对象,不能直接访问对象的字段

封装的关键在于,对外隐藏实现细节,接口完美地做到了这一点

经验

  • 在声明方法的参数、返回值,定义变量时,能用接口类型,就用接口类型,有更好的扩展性

你可能感兴趣的:(Java复习,java,开发语言)