首页 > 技术文章 > Java笔记: 继承成员覆盖和隐藏

cocode 2020-02-10 14:58 原文

在扩展类时,既可以向类中添加新的成员,也可以重新定义现有的成员。重定义现有成员的具体效果取决于成员的类型。本文不会详细的介绍概念,只简要总结覆盖(overriding,也叫重写)和隐藏(hiding)中最关键的地方。

方法覆盖的条件

概念:一个方法将方法的超类实现替换为自己的实现。覆盖并不要求两个方法类型完全一致,具体要求总结如下:

  • 签名: 覆盖方法的签名必须与超类相同,签名即为方法名和参数类型列表。
  • 返回类型: 覆盖方法返回类型可以是超类方法返回类型的子类型。
  • 访问权限: 覆盖方法可以改变访问修饰符,但只能提供更多的访问权限。
  • 异常: 覆盖方法抛出的异常可以比超类少,也可以是其子类型。

这些要求的规律就是覆盖的方法必须要与超类方法兼容,因为这样可以保证重写之后超类方法的契约仍然成立

继承成员的访问

调用哪个(非静态)方法是由对象的实际类型决定的,访问哪个字段是由引用的类型决定的。参考如下示例:

class SuperShow {
	public String str = "SuperStr";

	public void show() {
		System.out.println("Super.show: " + str);
	}
}

class ExtendShow extends SuperShow {
	public String str = "ExtendStr";

	public void show() {
		System.out.println("Extend.show: " + str);
	}

	public static void main(String[] args) {
		ExtendShow ext = new ExtendShow();
		SuperShow sup = ext;
		sup.show();
		ext.show();
		System.out.println("sup.str = " + sup.str);
		System.out.println("ext.str = " + ext.str);
	}
}

输出结果如下:

$ java ExtendShow
Extend.show: ExtendStr
Extend.show: ExtendStr
sup.str = SuperStr
ext.str = ExtendStr

根据之前所说的规则,show方法的调用总是会到ExtendShow类的版本上,这是由对象的实际类型决定的。而str的访问则是由引用决定,具体访问哪一个字段在编译期基于引用的类型决定。

推荐阅读