方法覆盖

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 + "日";
    }
}

// 多态机制:多态的存在让程序具有很强的扩展性。

 

posted @ 2020-06-07 21:06  xlwu丶lz  阅读(373)  评论(0编辑  收藏  举报