目录
🏀方法覆盖
🥅方法覆盖初体验
❤️回顾一下方法重载:
⭐️什么时候使用方法重载(overload)?
当在一个类当中,如果功能相似的话,建议将名字定义的一样,这样代码美观,并且方便编程。
⭐️什么条件满足之后能够构成方法重载(overload)?
条件一:在同一个类当中;
条件二:方法名相同;
条件三:参数列表不同(个数、顺序、类型);
❤️什么时候使用方法覆盖(override)?
⭐️子类继承父类之后,当继承过来的方法无法满足当前子类的业务需求时,子类有权利对这个方法进行重新编写,有必要进行“方法的覆盖”。
⭐️方法覆盖又叫做:方法重写,英语单词叫做:Override、Overwrite,都可以。⭐️重要结论:当子类对父类继承过来的方法进行“方法覆盖”之后,子类对象调用该方法的时候,一定执行覆盖之后的方法。
⭐️当我们代码怎么编写的时候,在代码级别上构成了方法覆盖(override)呢?
条件一:在两个类中,并且两个类必须要有继承关系。
条件二:重写之后的方法和之前的方法具有:
相同的返回值类型、
相同的方法名、
相同的形式参数列表。
条件三:访问权限不能更低,可以更高。(public->protected->private)
条件四:重写之后的方法不能比之前的方法抛出更多的异常,可以更少。
❤️注意事项:(这几个注意事项,当学习了下面的多态语法之后自然就明白了!)
注意1:方法覆盖只是针对于方法,和属性无关。
注意2:私有方法无法覆盖。
注意3:构造方法不能被继承,所以构造方法也不能被覆盖。
注意4:方法覆盖只是针对于“实例方法”,“静态方法覆盖”没有意义。
❤️例1:方法覆盖的引出
⭐️当前程序存在的问题(设计上的问题)?
鸟儿在执行move()方法的时候,最好输出的结果是:“鸟儿在飞翔”
但是当前的程序在执行move()方法的时候输出的结果是:"动物在移动!"
很显然Bird子类从Animal父类中继承过来的move()方法已经无法满足子类的业务需求。
public class OverrideTest01{
public static void main(String[] args){
// 创建鸟对象
Bird b = new Bird();
b.move(); // 让鸟儿移动
// 创建Cat类型对象
Cat c = new Cat();
c.move();// 让猫儿走猫步
}
}
// 父类
class Animal{
// 移动
public void move(){
System.out.println("动物在移动!");
}
}
// 子类--------------有继承关系
class Bird extends Animal{
// 子类继承父类中,有一些“行为”可能不需要改进,有一些“行为”可能面临着必须改进。
// 因为父类中继承过来的方法已经无法满足子类的业务需求。
//例如: 鸟儿在移动的时候希望输出鸟儿在飞翔!!!!
}
class Cat extends Animal{
//例如: 猫在移动的时候,我希望输出:猫在走猫步!!!!!!
}
❤️例2:使用方法覆盖
public class OverrideTest02{
public static void main(String[] args){
Bird b = new Bird();
b.move(); //----方法覆盖
b.sing(1000); //Animal sing....
Cat c = new Cat();
c.move(); //----方法重载
}
}
class Animal{
public void move(){
System.out.println("动物在移动!");
}
public void sing(int i){
System.out.println("Animal sing....");
}
}
//1.条件一:具有继承关系
class Bird extends Animal{
// 对move方法进行方法覆盖,方法重写,override
// 最好将父类中的方法原封不动的复制过来。(不建议手动编写)
// 方法覆盖,就是将继承过来的那个方法给覆盖掉了。继承过来的方法没了。
//2.条件二:重写之后的方法和之前的方法具有:相同的返回值类型、相同的方法名、相同的形式参数列表。
public void move(){
System.out.println("鸟儿在飞翔!!!");
}
//3.条件三:访问权限不能更低,可以更高
//protected表示受保护的。没有public开放。
// 错误:正在尝试分配更低的访问权限; 以前为public,此时只能为public或者更高
/*
protected void move(){
System.out.println("鸟儿在飞翔!!!");
}
*/
//4. 条件四:重写之后的方法不能比之前的方法抛出更多的异常,可以更少。
//错误:被覆盖的方法未抛出Exception,父类没有抛出异常!
/*
public void move() throws Exception{
System.out.println("鸟儿在飞翔!!!");
}
*/
// 分析:这个sing()和父类中的sing(int i)有没有构成方法覆盖呢?
// 没有,原因是,这两个方法根本就是两个完全不同的方法。
// 可以说这两个方法构成了方法重载吗?可以。
public void sing(){
System.out.println("Bird sing.....");
}
}
class Cat extends Animal{
// 方法重写
public void move(){
System.out.println("猫在走猫步!!!");
}
}
🥅方法覆盖经典案例
❤️例1
//一定要注意:方法覆盖/重写的时候,建议将父类的方法复制粘贴,这样比较保险。
public class OverrideTest03{
public static void main(String[] args){
// 创建中国人对象
// ChinaPeople p1 = new ChinaPeople("张三"); //err
// 错误原因:没有这样的构造方法,没有有参构造方法
ChinaPeople p1 = new ChinaPeople();// 能调用默认的无参构造方法!
p1.setName("张三");
p1.speak();
// 创建美国人对象
// AmericPeople p2 = new AmericPeople("jack");
// 错误原因:没有这样的构造方法
AmericPeople p2 = new AmericPeople();
p2.setName("jack");
p2.speak();
}
}
//------------------------人
class People{
private String name; // 属性
// 构造方法----不能继承
public People(){}
public People(String name){
this.name = name;
}
//setter and getter方法----能继承
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
// 人都会说话
public void speak(){
System.out.println(name + "....");
}
}
//----------中国人
class ChinaPeople extends People{ // 继承
//构造方法是不能被继承的,这里也没有写;默认是有一个无参的构造方法
// 中国人说话是汉语;所以子类需要对父类的speak()方法进行重写
public void speak(){
System.out.println(this.getName() + "正在说汉语");
}
}
//----------美国人
class AmericPeople extends People{
//构造方法是不能被继承的,这里也没有写;默认是有一个无参的构造方法
// 美国人说话是英语;所以子类需要对父类的speak()方法进行重写
public void speak(){
System.out.println(getName() + " speak english!");
}
}
❤️例2:覆盖toString方法
⭐️关于Object类中的toString()方法
1、toString()方法的作用是什么?
作用:将“java对象”转换成“字符串的形式”。2、Object类中toString()方法的默认实现是什么?
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
toString: 方法名的意思是转换成String
⭐️含义:调用一个java对象的toString()方法就可以将该java对象转换成字符串的表示形式。
public class OverrideTest04{
public static void main(String[] args){
// 创建一个日期对象
MyDate t1 = new MyDate();
// 调用toString()方法(将对象转换成字符串形式。)
// 问:你对这个输出结果满意吗?不满意,希望输出:xxxx年xx月xx日
//-------重写MyDate的toString()方法之前的结果
//System.out.println(t1.toString()); //MyDate@28a418fc
//-------重写MyDate的toString()方法之后的结果
System.out.println(t1.toString());
//-------直接输出一个引用的时候,println方法会自动调用引用的toString方法。
System.out.println(t1); //默认调用toString方法
MyDate t2 = new MyDate(2008, 8, 8);
System.out.println(t2); //2008年8月8日
//创建学生对象
Student s = new Student(1111, "zhangsan");
// 重写toString()方法之前
//System.out.println(s); //Student@87aac27
// 重写toString()方法之后
// 输出一个学生对象的时候,可能更愿意看到学生的信息,不愿意看到对象的内存地址。
System.out.println(s.toString());
System.out.println(s);//这两行结果是等价的
}
}
// 日期类
class MyDate {
private int year;
private int month;
private int day;
//构造方法
public MyDate(){
this(1970,1,1);
}
public MyDate(int year,int month,int day){
this.year = year;
this.month = month;
this.day = day;
}
//set和get接口方法
public void setYear(int year){
this.year = year;
}
public int getYear(){
return year;
}
public void setMonth(int month){
this.month = month;
}
public int getMonth(){
return month;
}
public void setDay(int day){
this.day = day;
}
public int getDay(){
return day;
}
// 调用toString()方法进行字符串转换的时候,
// 希望转换的结果是:xxxx年xx月xx日,这种格式。
public String toString() { //toString方法覆盖
return year + "年" + month + "月" + day + "日";
}
}
class Student{ //默认继承Object类,里面有toString方法
int no;
String name;
public Student(int no, String name){
this.no = no;
this.name = name;
}
// 重写,方法覆盖
public String toString() {
return "学号:" + no + ",姓名:" + name;
}
}
❤️小总结
⭐️关于Object类中toString()方法的覆盖?
(1) toString()方法存在的作用就是:将java对象转换成字符串形式。
(2)大多数的java类toString()方法都是需要覆盖的。因为Object类中提供的toString()
方法输出的是一个java对象的内存地址。⭐️方法重载和方法覆盖有什么区别?
(1)方法重载发生在同一个类当中。
(2)方法覆盖是发生在具有继承关系的父子类之间。
(3)方法重载是一个类中,方法名相同,参数列表不同。
(4)方法覆盖是具有继承关系的父子类,并且重写之后的方法必须和之前的方法一致:
方法名一致、参数列表一致、返回值类型一致。