思考1:什么时候我们会考虑使用方法覆盖"呢?
子类继承父类之后,当继承过来的方法无法满足当前子类的业务需求时,
子类有权利对这个方法进行重新编写,有必要进行方法的覆盖"。
方法覆盖又叫做:方法重写(重新编写),英语单词叫做: Override、Overwrite, 都可以
比较常见的:方法覆盖、方法重写、override
思考2:当我们代码怎么编写的时候,在代码级别上构成了方法覆盖呢?
条件一:两个类必须要有继承关系。
条件二:重写之后的方法和之前的方法具有:
相同的返回值类型、
相同的方法名、
相同的形式参数列表。条件三:访问权限不能更低,可以更高。(protected关键字)
[public权限比protected高 protected表示受保护的,没有public开放、](这个先记住。)条件四:重写之后的方法不能比之前的方法抛出更多的异常,可以更少。(先记住)
注意事项:
注意1:方法覆盖只是针对于方法,和属性无关。
注意2:私有方法无法覆盖。
注意3:构造方法不能被继承,所以构造方法也不能被覆盖。
注意4:方法覆盖只是针对于"实例方法","静态方法覆盖"没有意义。
分析:下列代码需要进行方法重写:
public class OverrideTest01
{
public static void main(String[] args){
// 创建一个鸟对象
Bird b =new Bird();
b.move(); // 动物在移动
b.eat(); //都喜欢吃
}
}
// 父类
class Animal
{
// 子类不需要改进的代码[用继承,子类不用再重写]
public void eat(){
System.out.println("都喜欢吃~");
}
// 移动
public void move(){
System.out.println("动物在移动~");
}
}
class Bird extends Animal
{
// 子类继承父类中,有些"行为"是不需要改进的比如eat()方法,有一些"行为"可能面临着必须改进
// 因为父类中继承过来的方法已经无法满足子类的业务需求
// 鸟儿在移动的时候希望输出的是鸟儿在飞翔~
}
class Cat extends Animal
{
// 猫在移动的时候,希望输出"猫在走猫步~"
}
方法重写后的代码:
public class OverrideTest01
{
public static void main(String[] args){
// 创建一个鸟对象
Bird b =new Bird();
b.move();
b.sing(1); //sing(int)方法传参时
b.sing(); //sing()方法不传参时
// 创建一个猫对象
Cat c =new Cat();
c.move();
}
}
// 父类
class Animal
{
// 移动
public void move(){
System.out.println("动物在移动~");
}
public void sing(int i){
System.out.println("Animal 在唱歌~");
}
}
class Bird extends Animal
{
// 鸟儿在移动的时候希望输出的是鸟儿在飞翔~
// 对move方法重写
// 最好将父类中的move方法原封不动的复制过来 (不建议手动编写)
public void move(){
System.out.println("鸟儿在飞翔~");
}
//分析:这个sing()和父类的sing(int i)方法是否发生了覆盖?
// 没有发生覆盖 [也就是说子类Bird不仅继承了父类的sing(int i)方法 还重新写了一个sing()方法
public void sing(){
System.out.println("bird 在唱歌~");
}
}
class Cat extends Animal
{
// 猫在移动的时候,希望输出"猫在走猫步~"
// 方法重写
public void move(){
System.out.println("猫儿在走猫步~");
}
}
运行结果:
条件三:访问权限不能更低,可以更高。(protected关键字)
public class OverrideTest01
{
public static void main(String[] args){
// 创建一个鸟对象
Bird b =new Bird();
b.move();
}
}
// 父类
class Animal
{
// 移动
public void move(){
System.out.println("动物在移动~");
}
}
class Bird extends Animal
{
protected void move(){ // 访问权限变低 报错:正在尝试分配更低的访问权限; 以前为public
System.out.println("鸟儿在飞翔~");
}
}
条件四:重写之后的方法不能比之前的方法抛出更多的异常,可以更少。
public class OverrideTest01
{
public static void main(String[] args){
// 创建一个鸟对象
Bird b =new Bird();
b.move();
}
}
// 父类
class Animal
{
// 移动
public void move(){
System.out.println("动物在移动~");
}
}
class Bird extends Animal
{
public void move() throws Exception { // 在子类重写后抛出异常 报错:被覆盖的方法未抛出Exception
System.out.println("鸟儿在飞翔~");
}
}public class OverrideTest01
{
public static void main(String[] args){
// 创建一个鸟对象
Bird b =new Bird();
b.move();
}
}
// 父类
class Animal
{
// 移动
public void move(){
System.out.println("动物在移动~");
}
}
class Bird extends Animal
{
public void move() throws Exception { // 在子类重写后抛出异常 报错:被覆盖的方法未抛出Exception
System.out.println("鸟儿在飞翔~");
}
}
运行结果:
典型覆盖案例
public class OverrideTest01
{
public static void main(String[] args){
// 创建中国人对象
ChinaPeople c =new ChinaPeople();
c.setName("jun");
c.speak();
//创建美国人对象
SmallDog s =new SmallDog();
s.setName("junker");
s.speak();
}
}
// 人
class People
{
private String name;
// 构造方法
public People(){}
public People(String name){
this.name =name;
}
// 设立关卡
public String getName(){
return this.name;
}
public void setName(String name){
this.name =name;
}
// 实例方法
public void speak(){
System.out.println(this.name+"人都会说话...");
}
}
// 中国人
// 中国人说中国话 所以子类需要对父类的speak()方法重写
class ChinaPeople extends People
{
private String no;
// 实例方法
public void speak(){
System.out.println(this.getName()+":用汉语说话...");
}
}
// 美国人
class SmallDog extends People{
public void speak(){
System.out.println(this.getName()+":汪汪汪~");
}
}
静态方法不存在方法重写
1、方法覆盖必须和多态机制联合在一起才有意义
Animal a =new Cat();
a.move();
要的是什么效果?
编译的时候move()的方法是Animal类的方法,然后静态绑定
运行的时候自动调用到子类重写的move()方法上
假如没有多态机制,只有方法覆盖机制,你觉得有意义吗?
没有多态机制的话,方法覆盖可有可无
2、静态方法中存在方法重写吗?
静态方法的执行不需要对象,而方法重写是子类继承父类存在对象的关系,所以说静态方法不存在方法重写
// 测试程序
public class OOTest01
{
public static void main(String[] args){
/*
静态方法是"类名."的方式进行访问,不建议使用"引用."
*/
Animal a =new Cat();
a.doSome(); // 结果:Animal的doSome方法执行 而不是Cat的doSome方法 所以静态方法不存在方法重写
}
}
// 父类
class Animal
{
public static void doSome(){
System.out.println("Animal的doSome方法执行");
}
}
// 子类
class Cat extends Animal
{
public static void doSome(){
System.out.println("Cat的doSome方法执行");
}
}
私有方法不能被重写
/*
私有方法不能被覆盖
*/
public class OOTest02
{
private void doSome(){
System.out.println("私有方法的doSome开始执行");
}
public static void main(String[] args){
// 多态
OOTest02 o =new T();
o.doSome(); // 输出结果:私有方法的doSome开始执行
// 能输出私有方法的doSome 私有方法必须在本类中执行,在其他类则不能访问私有方法和私有变量
// 输出结果说明子类没有发生方法重写机制
}
}
class T extends OOTest02
{
// 尝试重写父类的doSome方法[重写前:需要先继承]
public void doSome(){
System.out.println("子类T的doSome方法开始执行");
}
}