java子类继承方法和接口方法重名/冲突(下)

java子类继承方法和接口方法重名/冲突(下)

在上篇文章java子类继承方法和接口方法重名/冲突(上)中提到,只要从父类继承的方法权限是public,就能覆盖接口的同名方法。

然而还有一种情况会让人生疑:jdk1.8后,接口的方法也能提供默认实现,那么如果从父类方法不是抽象方法,接口的同名方法也提供了默认实现,那么子类的方法是否会冲突,或是否需要重写?

我们还是用上文用过的例子:

abstract class Fish{
	private boolean isFast;
	abstract void desrcibe();
	protected void swim() {//父类提供的非抽象方法
		System.out.println("我能游泳");
	}
}
interface aquatic{
	boolean isAquatic = true;
	default void swim() {
		System.out.println("我天生会游泳");//注意该处接口提供了默认实现
	};
	void breath();
}
class Carp extends Fish implements aquatic{//暂时不重写swim函数
	@Override
	public void breath() {
		System.out.println("我用鳃呼吸");
	}
	@Override
	void desrcibe() {
		System.out.println("这是一条鲤鱼");
	}
}

在上文没有提供接口方法的默认实现的情况下,protected权限的swim无法重写接口中的方法,而这次我们提供了接口方法的默认实现,结果怎样呢?

IDE继续报错:The inherited method Fish.swim() cannot hide the public abstract method in aquatic

其实原因是:父类的非私有方法在子类没有重写的情况下是一定要继承的,而接口的default方法仅是在子类没有提供实现方法时才会被调用,也就是说,接口的default方法是优先被覆盖的
于是,从父类继承而来的protected方法依然覆盖不了接口方法

为了证明上述观点,我们将Fish中swim的权限改为public:

abstract class Fish{
	private boolean isFast;
	abstract void desrcibe();
	public void swim() {//父类提供的非抽象方法
		System.out.println("我能游泳");
	}
}

再调用Carp的swim方法,看它的方法实现到底是父类的非抽象方法还是接口提供的默认方法:

public class source{
	public static void main(String[] args) {
		Carp myCarp = new Carp();
		myCarp.swim();
	}
} 

亲自试一试:(点击右上角的运行,你也可以修改Fish中的swim方法为protected,再试试能不能运行)

运行结果:

我能游泳

说明子类方法的实现的确是从父类继承的方法体,而接口的swim方法此时被父类方法重写了
结论:

父类的非私有方法必须继承
接口的default方法优先被覆盖
当父类方法和接口方法冲突时,看父类方法能不能覆盖接口方法,如果不能,则编译报错

5+
Rhett Peng

软件工程大三在读学生,用个人网站记录学习动态

说点什么

avatar