方法覆盖
1 方法覆盖
1.1 什么时候考虑方法覆盖?
父类中的方法无法满足子类的业务需求,子类有必要对继承过来的方法进行覆盖。
1.2 什么条件 满足的时候构成方法覆盖?
第一:有继承关系的两个类。
第二:具有相同方法名、返回值类型、形式参数列表。
第三:访问权限不能更低。
第四:抛出异常不能更多。
1.3 关于Object类中toString()方法的覆盖?
toString()方法存在的作用就是:将java对象转换成字符串形式。
大多数的java类的toString()方法都是需要覆盖的。因为Object类中提供的toString()方法输出的是一个java对象的内存地址。
至于toString()方法具体怎么进行覆盖?
格式可以自己定义,或者听需求的。(听项目要求的。)
1.4 方法重载和方法覆盖有什么区别?
方法重载发生在同一个类当中。
方法覆盖是发生在具有继承关系的父子类之间。
方法重载是一个类中,方法名相同,参数列表不同。
方法覆盖是具有据称关系的父子类,并且重写之后的方法必须和之前的方法一致:
方法名一致、参数列表一致、返回值类型一致。
案例1:
/* 当前程序存在的问题(设计上的问题)???? 鸟儿在执行move()方法的时候,最好输出的结果是:“鸟儿在飞翔” 但是当前的程序在执行move() 方法的时候输出的结果是:“动物在移动”! 很显然Bird子类从Animal父类中继承过来的move()方法已经无法满足子类的业务需求。 */ public class OverrideTest01{ public static void main(String[] args){ // 创建鸟儿的对象 Bird b = new Bird(); // 让鸟儿移动 b.move(); Cat c = new Cat(); c.move(); } } // 父类 class Animal{ // 但是有一些方法是需要覆盖的 // 移动 实例方法 public void move(){ System.out.println("动物在移动!!!!"); } // 这个方法可能不需要覆盖 public void doSome(){ } } // 子类 class Bird extends Animal{ // 子类继承父类中,有一些“行为”可能不需要改进,有一些“行为”可能面临着必须改进。 // 因为父类中继承过来的方法已经无法满足子类的业务需求 // 鸟儿在移动的时候希望输出鸟儿在飞翔!!!! } class Cat extends Animal{ // 猫在移动的时候,我希望输出:猫在走猫步!!!!! }
案例2:
/* 回顾一下方法重载!!!! 什么时候考虑使用方法重载overLoad? 当在一个类当中,如果功能相似的话,建议将名字定义的一样,这样代码美观,并且方便编程。 什么条件满足之后能够成方法重载overload? 条件一:在同一个类当中 条件二:方法名相同 条件三:参数列表不同(个数、顺序、类型) ------------------------------------------------------------------------------------------------- 什么时候我们会考虑使用“方法覆盖”呢? 子类继承父类之后,当继承过来的方法无法满足当前子类的业务需求时, 子类有权利对这个方法进行重新编写,有必要进行“方法覆盖”。 方法覆盖又叫做:方法重写,英语单词叫做:Override、Overwrite,都可以。 比较常见的:方法覆盖、方法重写(重新编写)、Override 重要结论: 当子类对父类继承过的方法进行“方法覆盖”之后 子类对象调用该方法的时候,一定执行覆盖之后的方法。 当我们代码怎么编写的时候,在代码级别上构成了方法覆盖呢? 条件一:两个类必须要有继承关系。 条件二:重写之后的方法和之前的方法具有" 相同的返回值类型、 相同的方法名、 相同的形式参数列表。 条件三:访问权限不能更低,可以更高(这个先记住)。 条件四:重写之后的方法不能比之前的方法抛出更多的异常,可以更少。(这个先记住) 这里还有几个注意事项:(这几个注意事项,当学习了多态语法之后自然就明白了。) 注意1:方法覆盖只是针对于方法,与属性无关。 注意2:私有方法无法覆盖。 注意3:构造方法不能被继承,所以构造方法也不能被覆盖。 注意4:方法覆盖只是针对于“实例方法”,静态方法覆盖没有意义。 */ 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(){ protected void move() throws Exception{// 这样就可以 System.out.println("动物在移动!"); } public void sing(int i){ System.out.println("Animal sing......"); } } class Bird extends Animal{ // 对move方法进行方法覆盖,方法重写,override // 最好将父类中的方法原封不动的复制过来。(不建议手动编写) // 方法覆盖,就是将继承过来的那个方法给覆盖掉了。继承过来的方法没了。 public void move(){ System.out.println("鸟儿在飞翔!!!!"); } // 错误: Bird中的move()无法覆盖Animal中的move() // 被覆盖的方法未抛出Exception /* public void move() throws Exception { System.out.println("鸟儿在飞翔!!!!"); } */ // protected表示受保护的。没有public开放。 // 错误: Bird中的move()无法覆盖Animal中的move() 正在尝试分配更低的访问权限; 以前为public /* protected void move(){ System.out.println("动物在移动!"); } */ // 分析:这个sing方法和父类中的sing(int i)发生了方法的重写了吗? // 没有,原因是:这两个方法根本就是两个完全不同的方法。 // 可以说这两个方法构成了方法重载吗?可以。 public void sing(){ System.out.println("move sing......"); } } class Cat extends Animal{ // 方法重写(重新编写) public void move(){ System.out.println("猫儿在走猫步!!!!"); } }
比较经典的方法覆盖案例:
/* 方法覆盖比较经典的案例 一定要注意:方法覆盖/重写的时候,建议将父类的方法复制黏贴,这样比较保险。 */ public class OverrideTest03{ public static void main(String[] args){ // 创建中国人对象 ChinaPeople c = new ChinaPeople(); c.setName("张三"); c.speak(); // 创建美国人对象 AmericPeople a = new AmericPeople(); a.setName("lisi"); a.speak(); } } //人 class People{ // 属性 private String name; // 构造方法 public People(){} public People(String name){ this.name = name; } // getter and setter 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(this.getName() + " speak english"); } }
覆盖Object中toString()方法案例:
public class OverrideTest04{ public static void main(String[] args){ // 创建日期对象 MyDate date = new MyDate(); // 调用toString()方法(将对象转换成字符串形式。) // 问:你对这个输出结果满意吗?不满意 希望输出xx年xx月xx日 // 什么时候需要使用方法覆盖???? // System.out.println(date.toString());// MyDate@54bedef2 // 重写MyDate的toString() 方法之后的结果 System.out.println(date.toString()); // 大家是否还得:当输出一个引用的时候,println方法会自动调用引用的toString方法。 System.out.println(date); MyDate date2 = new MyDate(2008,8,8); System.out.println(date2); } } class MyDate{// 如果你不继承的话 默认继承的是Object // 封装私有属性 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; } // getter and setter 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; } // 从Object类中继承过来的那个toString() 方法已经无法满足我业务需求了。 // 我在子类MyDate中有必要对父类的toString()方法进行覆盖/重写。 // 我的业务要求是:调用toString()方法进行字符串的时候,希望转换的结果是:xxxx年xx月xx日,这种格式。 // 重写一定要赋值黏贴,不要手动编写,会错的。 public String toString(){ return year + "年" + month + "月" + day + "日"; } } // 多态机制:多态的存在让程序具有很强的扩展性。