• 菜鸡的Java笔记 第二十


    1.方法的覆写
        当子类定义了与父类中的完全一样的方法时(方法名称,参数类型以及个数,返回值类型)这样的操作就称为方法的覆写
        范例:观察方法的覆写

    class A{
        public void print(){
            System.out.println("******************");
        }
    }
    class B extendsa A{
        
        }    
    }
    
    public class inherit{
        public static void main(String args[]){
            B b= new B();
            b.print();
        }
    }
    /*
    结果:
    ******************
    */


        此时B是A的子类,并且B类中没有定义任何的方法。此时B类将直接继承A类中的println()方法执行
        范例:发生覆写

    class A{
        public void print(){
            System.out.println("******************");
        }
    }
    class B extendsa A{
        public void print(){  // 方法名称一样
            System.out.println("!!!!!!!!!!!!!!!!!!");
        }    
    }
    
    public class inherit{
        public static void main(String args[]){
            B b= new B();
            b.print();
        }
    }
    /*
    结果:
    !!!!!!!!!!!!!!!!!!
    */

    ... 

    class A{
        public void print(){
            System.out.println("******************");
        }
    }
    class B extendsa A{
        public void print(){  // 与父类的方法完全一样
            System.out.println("!!!!!!!!!!!!!!!!!!");
        }    
    }
    class C extendsa A{
        public void print(){
            System.out.println("¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥");
    }
    public class inherit{
        public static void main(String args[]){
            C c = new C();
            c.print();
        }
    }
    /*
    结果:
    ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
    */      

            (主要是看 new 谁)   
            此时的程序之中使用了B类进行对象的实例化操作,并且在B类中已经明确的覆写了A类中的print()方法
            那么最终所调用的一定就是被覆写过的方法
            
        范例:分析方法覆写的含义

    class Person{
        private String name;
        private int age;
        public void setName(String name){
            this.name = name;
        }
        public void setAge(int age){
            this.age = age;
        }
        public String getName(){
            return this.name;
        }
        public int getAge(){
            return this.age;
        }
        public String getlnfo(){
            return     "姓名:"+this.name
                    +",年龄:"+this.age;
        }
    }
    class Student extends Person{  // Student 是Person 的子类
        private String school; // 子类自己扩充的属性
        public void setSchool(String school){
            this.school = school;
        }
        public String getSchool(){
            return this.school;
        }
        
    }
    public class inherit{
        public static void main(String args[]){
            Student stu = new Student();// 实例化子类对象
            stu.setName("少爷");//通过Person类继承而来
            stu.setAge(20);//通过Person类继承而来
            stu.setSchool("清华");//子类自己扩充的属性
            System.out.println(stu.getlnfo());
        }
    }
    /*
    结果: (问题:少了School 这个值)
    姓名:少爷,年龄:20
    */

    ******************************************        

    class Person{
        private String name;
        private int age;
        public void setName(String name){
            this.name = name;
        }
        public void setAge(int age){
            this.age = age;
        }
        public String getName(){
            return this.name;
        }
        public int getAge(){
            return this.age;
        }
        public String getlnfo(){
            return     "姓名:"+this.name
                    +",年龄:"+this.age;
    }
    }
    class Student extends Person{  // Student 是Person 的子类
        private String school; // 子类自己扩充的属性
        public void setSchool(String school){
            this.school = school;
        }
        public String getSchool(){
            return this.school;
        }
        public String getlnfo(){ // 保留方法名称,但是有需要对功能进行扩充
            return     super.getlnfo()
                    +"学校:"+this.school;
            // return     "姓名:"+super.getName()
                    +",年龄:"+super.getAge()
                    +"学校:"+this.school;
        }
    public class inherit{
        public static void main(String args[]){
            Student stu = new Student();// 实例化子类对象
            stu.setName("少爷");//通过Person类继承而来
            stu.setAge(20);//通过Person类继承而来
            stu.setSchool("清华");//子类自己扩充的属性
            System.out.println(stu.getlnfo());
        }
    }        

            实质上所谓的方法覆写原因:
            父类中定义的方法名称是其他程序所认可的名称,属于使用的习惯
            但是子类在使用的过程之中,发现原始的方法不能够支持自己的操作,而且又需要保留猪方法名称,这样才出现了覆写的概念
            并且通过以上的分析可以发现一点:
                this.方法():会先找本类中是否有指定的方法,如果本类没有则使用父类继承而来的方法
                super.方法():不查找本类的方法,而直接找父类的方法
            但是覆写本身也是有严格要求的:被覆写的方法不能够拥有比父类更为严格的访问控制权限。
            对于访问的控制权限严格来讲一共有四个,已经学习过三个:private<default(friend)<public
            按照以上的思路,如果说现在父类中的方法使用了public访问权限声明,那么子类只能够使用public 而如果父类使用了default访问权限声明,那么子类可以使用public或default
        范例:错误的覆写

    class A{
        public void print(){
            System.out.println("******************");
        }
    }
    class B extendsa A{
        void print(){  // 此时的方法访问权限严格
            System.out.println("!!!!!!!!!!!!!!!!!!");
        }    
    }
    public class inherit{
        public static void main(String args[]){
            B b= new B();
            b.print();
        }
    }
    /*
    结果:出错
    */

           
            但是此时又会出现这样一种情况,如果父类中的方法使用了private呢?那么子类覆写方法时如果使用了default也属于权限扩大这样可以覆写吗?
        范例:正常覆写

    class A{
        public void fun(){
            this.print();
        }
        public void print(){
            System.out.println("******************");
        }
    }
    class B extendsa A{
        public void print(){  
            System.out.println("!!!!!!!!!!!!!!!!!!");
        }    
    }
    public class inherit{
        public static void main(String args[]){
            B b= new B();
            b.fun();
        }
    }
    /*
    结果:
    !!!!!!!!!!!!!!!!!!
    */

           
            下面将父类中的println()方法权限修改为private

    class A{
        public void fun(){
            this.print();
        }
        private void print(){
            System.out.println("******************");
        }
    }
    class B extendsa A{
        public void print(){  
            System.out.println("!!!!!!!!!!!!!!!!!!");
        }    
    }
    public class inherit{
        public static void main(String args[]){
            B b= new B();
            b.fun();
        }
    }
    /*
    结果:
    ******************
    */

           
            从权限的角度来看此时应该符合覆写的要求
            通过结果可以发现,此时子类并没有进行方法的覆写所以就可以得出结论:
                父类中private声明的方法不能够被子类所覆写,而且最重要的是这样的操作几乎没有意义
            在实际之中对于方法的定义,95%的情况下都只会使用public声明

    在进行方法覆写之后都会存在有一个就近取用的关系,如果面对本类方法自己调用自己的情况,因为默认情况下调用本类方法时都会采用“this.方法()” 的形式处理
            而在使用this调用结构的时候,会首先找到本类如果本类找不到的操作再去查找父类
            为了可以不查找本类而直接找到父类,建议使用“ super.方法() ” 的形式调用
            
            以后为了表示明确,强烈建议:子类访问父类方法前都是 super
        
        面试题:请解释Overloading与Override的区别?在进行Overloading的时候能否返改变回值类型

    区别 方法重载  方法覆写
    单词 Overloading  Override
    范围 发生在一个类中 发生在继承关系之中
    定义 方法名称相同,参数的类型以及个数不同 方法名称相同,参数的类型以及个数,返回值全部相同
    权限 没有权限要求 被覆写的方法不能拥有比父类更为严格的访问控制权限


            在进行方法重载的时候可以使用不同的返回值类型,但是从设计的标准来讲不建议使用


     2.属性的覆盖
        当子类定义了与父类属性名称相同的属性时,就称为属性的覆盖
        范例:观察属性的覆盖

    class A{
        String info = "mysterious";
    }
    class B extendsa A{
        int info = 100; // 名称相同
        public void print(){
            System.out.println(this,info);
            System.out.println(super.info);
        }
    }
    public class inherit{
        public static void main(String args[]){
            B b= new B();
            b.print();
        }
    }
    /*
    结果:
    100
    mysterious
    */

           
            从实际开发的标准要求来讲,类中的属性必须使用private封装,那么一旦使用了private封装属性覆盖没有意义了
        面试题:请解释this与super的区别?

    区别 this  super
    概念 表示调用本类属性(this.属性),本类方法(this.方法,this()) 调用父类属性(super.属性),父类方法(super.方法(),super())
    构造要求 调用构造方法是必须放在构造方法的首行,所以this()与super()不能够同时出现,但是子类永远会去调用父类中的构造方法 调用构造方法是必须放在构造方法的首行,所以this()与super()不能够同时出现,但是子类永远会去调用父类中的构造方法
    特殊要求 表示当前对象  


            使用this实际上会先从本类开始查找所需要的内容,如果没有去查询父类,而如果使用的是super则表示不查询本类直接查找父类的定义

    总结
    1.所有类中的属性都必须使用private定义,这样一来覆盖属性就没有任何意义了
    2.方法的覆写调用特点:
        看实例化的是那个子类的对象(new 出现在哪里或者说是new哪个类)
        观察调用的方法是否已经被该子类覆写,如果覆写则调用被覆写的方法,如果没有覆写则调用从父类继承而来的方法



  • 相关阅读:
    Bash awk 基本入门
    MFC 创建文件
    MFC listbox array 使用
    MFC CString 字符串截取
    CStudioFile 读取 txt 文件数据
    C++ 取整 取余
    MFC 单文档应用程序 dialog 变量传递
    MFC 字符串截取成数组 wcstok
    写入文件
    MFC dialog 间 交互[2]
  • 原文地址:https://www.cnblogs.com/mysterious-killer/p/10074003.html
Copyright © 2020-2023  润新知