Java 中,一个类可以实现多个接口,这是通过使用 implements 关键字实现的。实现多个接口可以使类具有多种行为和能力。里氏替换原则(Liskov Substitution Principle,LSP)是面向对象设计中的一项重要原则,确保在使用基类的地方可以透明地使用其子类。本文主要介绍Java中一个类实现个多个接口与里氏替换原则问题。

1、里氏替换原则

1)所有使用基类的地方必须能够使用子类进行替换,而程序的行为不会发生任何变化(替换为子类之后不会产生错误或者异常)。只有这样,父类才能真正被复用,子类能够在父类的基础上增减新的属性和行为。才能真正的实现多态行为。

2)当子类继承父类的时候,子类就拥有了父类的属性和行为。

3)里氏替换原则是实现开闭原则的重要方式之一。由于使用基类对象的地方可以使用子类对象,因此程序中尽量使用基类类型进行定义,而在运行的时候确定子类类型,子类对象替换父类对象。

2、类实现多个接口

有一个Example实现了Interface1Interface2两个接口:

class Example implements Interface1, Interface2 {
    ...
}

可以使用如下代码实例化Example类:

Interface1 example = new Example();

我只能调用Interface1方法,而不是Interface2方法:

((Interface2) example).someInterface2Method();

或者

if (example instanceof Interface2) {
    ((Interface2) example).someInterface2Method();
}

上面那样写法感觉和里氏替换原因有点冲突,也许是接口设计的问题,可能是两个接口之间没有松耦合,就不应该将两个接口分离开。

也可以用如下方法,在写一个接口包装一下,这个接口实现上面两个接口:

interface Interface3 extends Interface1, Interface2 {}

然后可以在代码中这样使用:

public void doSomething(Interface3 interface3){
    ...
}

另一种方式(在我看来,更好的方法)是使用每种方法的泛型:

public <T extends Interface1 & Interface2> void doSomething(T t){
    ...
}

使用上面泛型的实现方式比前者更少受限制,因为泛型类型T被动态推断并因此导致更少的耦合(类不必实现特定的接口)。所以我们也应该注意避免最终因设计不正确而可能面临更多问题

推荐文档