阿里云【名师课堂】Java面向对象开发57 ~ 59:覆写

57:方法覆写

概念

方法覆写指的是子类定义了与父类方法名称、参数类型及个数完全相同的方法,凡是被覆写的方法不能拥有比父类更严格的访问控制权限。
范例:观察简单的方法覆写

class Person {
	public void printInfo() {
		System.out.println("【Person类】printInfo()方法") ;
	}
}

class Student extends Person {
	public void printInfo() { // 注意方法名完全相同
		System.out.println("【Student类】printInfo()方法") ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Student stu = new Student() ; // 子类实例化对象
		stu.printInfo();
	}
}

在这里插入图片描述
使用覆写时一定要关注以下两点

  • 当前使用的对象是哪个类new的(哪个类实例化的);
  • 调用方法时,如果某方法已经被子类覆写了,则调用的一定是被覆写的方法。

访问权限

再次强调:凡是被覆写的方法不能拥有比父类更严格的访问控制权限

  • 访问控制权限:private < default < public
  • 就是说,如果父类方法使用public权限,子类方法只能是public权限;如果父类default权限,子类可以是defaultpublic
    • 这时需要关注private权限,如果父类方法被private定义,那么表示该方法只能被父类调用,对子类而言根本没有这个方法。
  • 范例:错误的覆写
class Person {
	void printInfo() {  // default权限
		System.out.println("【Person类】printInfo()方法") ;
	}
}

class Student extends Person {
	private void printInfo() { // 访问权限变严格了
		System.out.println("【Student类】printInfo()方法") ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Student stu = new Student() ; // 子类实例化对象
		stu.printInfo();
	}
}
//输出:错误提示: Student中的printInfo()无法覆盖Person中的printInfo()
  • 范例:观察private权限
class Person {
	public void method(){
		this.printInfo() ;
	}
	private void printInfo() {
		System.out.println("【Person类】printInfo()方法") ;
	}
}

class Student extends Person {
	// 这时这个方法只是子类定义的新方法,和父类一点关系没有
	public void printInfo() {
		System.out.println("【Student类】printInfo()方法") ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Student stu = new Student() ; // 子类实例化对象
		stu.method();
	}
}
// 这时输出为:【Person类】printInfo()方法
// 如果把父类方法private换为default或public,输出为:【Student类】printInfo()方法

结论:绝大多数情况下写重载时访问权限就用public。

重载和覆写的区别

请回顾:《阿里云【名师课堂】Java面向对象开发8:构造方法与匿名对象》中的方法重载部分。

区别重载覆写
英文OverloadOverride
概念方法名称相同,参数的种类、个数不同方法名称、返回值类型、参数类型及个数完全相同
范围发生在一个类中发生在继承关系中
限制没有权限要求凡是被覆写的方法不能拥有比父类更严格的访问控制权限
  • 重载时返回值是否可以不同?
    • 方法重载时返回值可以不同,但是良好的设计上要求返回类型相一致

58:属性覆盖(了解)

当子类定义了与父类中属性名称完全相同的属性时就叫做属性的覆盖。

class Person {
	public String info = "it was called yellow" ;
	public void printInfo() {
		System.out.println("【Person类】printInfo()方法") ;
	}
}

class Student extends Person {
	public int info = 3000 ;
	public void printInfo() {
		System.out.println(info) ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Student stu = new Student() ; // 子类实例化对象
		stu.printInfo() ;
	}
}

在这里插入图片描述
这个操作实际上没有意义,因为在实际操作中我们会用private定义属性,这时子类根本不知道父类中有哪些属性,也就不存在对父类属性进行重载操作。
结论:写属性时尽量不要有重名。

59:super关键字

在之前的子类对象实例化操作的讲解时介绍了super(),当时是子类调用父类方法时才使用。
那么在进行覆写的操作过程中,子类也可以使用super.方法()或者super.属性明确调用父类的方法或属性。

调用父类方法

范例:观察一个程序

class Person {
	public void printInfo() {
		System.out.println("【Person类】printInfo()方法") ;
	}
}

class Student extends Person {
	public void printInfo() {
		System.out.println("【Student类】printInfo()方法") ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Student stu = new Student() ; // 子类实例化对象
		stu.printInfo() ;
	}
}

对于这段程序,输出是:【Student类】printInfo()方法

  • 首先,实例化子类对象stu,然后stu调用子类中的printInfo方法。
  • 因为子类覆写了父类的printInfo方法。

如果实例化操作改为:Person stu = new Person() ;,输出是:【Person类】printInfo()方法

  • 因为实例化了父类对象,直接调用父类中的printInfo方法。

如果将子类改为:

class Student extends Person {
	public void printInfo() {
		printInfo() ; // this.printInfo() ;
		System.out.println("【Student类】printInfo()方法") ;
	}
}

输出为:java.lang.StackOverflowError,即栈溢出。

  • 因为这里是递归调用,这里的printInfo() ;就相当于this.printInfo() ;
  • this起到的作用为:先在本类中查找所需要的方法,如果本类没有,则去找父类中方法进行调用。所以这里就是在自己的printInfo() ;中调用printInfo() ;

如果将子类改为:

class Student extends Person {
	public void printInfo() {
		super.printInfo() ;
		System.out.println("【Student类】printInfo()方法") ;
	}
}

输出为:
在这里插入图片描述
为什么?

  • 使用super关键字之后不在本类寻找方法,而是直接前往父类调用父类中的方法。
  • 这里就是先输出父类的printInfo() ;再输出自己的printInfo() ;

调用父类属性

范例:观察调用父类属性
先回顾第58讲中的属性覆盖程序,子类中的System.out.println(info) ; // info=this.info语句输出的永远是3000,因为它输出的是自己的info。
要想输出父类的info应该:在子类的printInfo方法中添加:System.out.println(super.info) ;
在这里插入图片描述

super与this

通过分析我们发现:super与this的使用形式上高度相似,但是二者最大区别在于:super是子类访问父类的操作,this是在本类自身中访问处理的操作。

区别thissuper
概念访问本类中的属性、方法由子类访问父类中的属性、方法
查找范围先查找本类,如果本类没有则调用父类不查找本类,直接调用父类
特殊表述当前对象没有类似“表示父类对象”的概念

覆写总结:

  • 子类覆写父类的方法是因为父类的方法功能不足;
  • 方法覆写时统一使用public权限,注意返回值、名称的完全相同
  • 以后在子类中调用父类方法时一定加上super关键字。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值