美文网首页程序员
Java学习14:继承、方法覆盖

Java学习14:继承、方法覆盖

作者: 苦难_69e0 | 来源:发表于2020-10-09 13:55 被阅读0次

    继承extends

    继承的作用:
    基本作用:子类继承父类,代码可以得到复用。(这个不是重要的作用,是基本作用。)
    主要(重要)作用:因为有了继承关系,才有了后期的方法覆盖和多态机制。
    java中继承的语法格式:
    class 类名 extends 父类名{
    类体;
    }
    继承的相关特性:
    1、B类继承A类,则成A类为超类(superclass)、父类、基类,B类则称为子类(subclass)、派生类、扩展类。

    class A()
    class B extends A()
    我们平时聊天说的比较多的是:父类和子类。
    superclass 父类
    subclass 子类

    2、java中的继承只支持单继承,不支持多继承,c++中支持多继承,这也是java体现简单性的一点,换句话说,java中不允许这样写代码:
    class B extends A,C{},这是错误的。

    3、虽然java中不支持多继承,但有的时候会产生间接继承的效果,
    例如:class C extends B , class B extends A , 也就是说,C直接继承B,其实C还简介继承A。

    4、java中规定,子类继承父类,除构造方法不能继承之外,剩下都可以继承。但是私有的属性无法在子类中直接访问。(父类中private修饰的不能在子类中直接访问,可以通过间接的手段去访问)

    5、java中的类没有显示的继承任何类,则默认继承Object类,Object类是java语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有Object类型中所有的特征。

    6、继承也存在一些缺点,例如:CreditAccount类继承Account类会导致他们之间的耦合度非常高,Account类发生改变之后会马上影响到CreditAccount类。
    耦合度高,父类修改,子类受牵连。

    子类继承父类之后,能使用子类对象调用父类方法么?
    实际上这个问题有点蹊跷。
    蹊跷在于:能使用子类对象调用父类方法
    本质上,子类继承父类之后,是将父类继承过来的方法归为自己所有。实际上调用的也不是父类的方法,是他子类自己的方法(因为已经继承过来了,就属于自己的。)
    那自然是可以了,子类继承父类之后,这个方法就属于子类了,当然可以使用子类对象来调用。

    在实际开发中,满足什么条件的时候,我可以使用继承呢?
    凡是采用“is a”能描述的,都可以继承。
    例如:
    Cat is a Animal:猫是一个动物
    Dog is a Animal:狗是一个动物
    CreditAccount is a Accout:信用卡账户是一个银行账户
    ......
    假设以后的开发中,有一个A类,有一个B类,A类和B类确实也有重复的代码,那么他们两个之间就可以继承么?
    不一定,还是要看一看他们之间是否能够使用is a 来描述。

    java为什么比较好学?
    是因为Java内置了一套旁发的类库,程序员不需要从0开始写代码,程序员可以基于这套庞大的类库进行“二次”开发。(开发速度较快,因为JDK内置的这套库实现了很多基础的功能。)
    例如:String 是SUN编写的字符串类、System是SUN编写的系统类。
    这些类都可以拿来直接使用。

    分析System.ou.println("Hello World!");
    System.out中,out后面没有小括号,说明out是变量名。
    另外System是一个类名,直接使用类名System.out,说明out是一个静态变量。
    System.out返回一个对象,然后采用“对象.”的方式访问println()方法。
    System.ou.println("Hello World!");*中System、out、println都是标识符。
    在editplus中的红色字体,表示这个类是SUN公司的JDK写好的一个类。

    任何一个类,没有显示继承任何类,默认继承Object,那么Object类当中又哪些方法呢?老祖宗为我们提供了哪些方法?
    toString()方法

    public class Test{
      //Test默认继承Object
      //Test类当中是有toString()方法
      //不过toString()方法是一个实例方法,需要创建对象才能调用。
    
      /*
      public String toString(){
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
      }
      */
    
      public static void main(String[] args){
        //先new对象
        Test et = new Test();
        String reValue = er.toString();
    
        //2f92e0f4 可以“等同”看做对象在堆内存当中的内存地址。
        //实际上是内存地址i经过“哈希算法”  得出的16进制结果。
        System.out.println(reValue);//Test@2f92e0f4
    
        //如果直接输出“引用”呢?
         System.out.println(et);//Test@2f92e0f4
      }
    }
    

    Object类当中有很多方法,大部分看不懂,其中有一个叫做toString()的,经测试发现:
    System.out.println(引用);
    当直接输出一个“引用”的时候,println()方法会先自动调用“引用.toString()”,然后输出toString()方法的执行结果。

    注意:当源码当中一个方法以“;”结尾,并且修饰符列表中有“native”关键字表示底层调用c++写的dll程序(dll动态链接库文件)

    方法覆盖

    子类继承父类中,有一些“行为”可能不需要改进,,有一些“行为”可能面临着必须改进。因为父类继承过来的方法已经无法满足子类的业务需求。
    什么时候我们考虑使用“方法覆盖”?
    子类继承父类之后,当继承过来的方法无法满足当前子类的业务需求时,子类有权利对这个方法进行重新编写,有必要进行“方法的覆盖”。

    方法覆盖又叫做方法重写,英语单词叫做:Override、Overwrite,都可以。
    比较常见的:方法覆盖、方法重写、Override

    在进行方法覆盖的时候,最好将父类中的方法原封不动的复制过来。(不建议手动编写)
    方法覆盖,就是将继承过来的哪个方法给覆盖掉了,继承过来的方法没了。

    重要结论:当子类对父类继承过来的方法进行“方法覆盖”之后,子类对象调用该方法的时候,一定执行覆盖之后的方法。

    当我们代码怎么编写的时候,在代码级别上构成了方法覆盖呢
    条件一:两个类必须要有继承关系。
    条件二:重写之后的方法和之前的方法具有:相同的返回值类型、相同的方法名、相同的形式参数列表。
    条件三:访问权限不能更低,可以更高。
    条件四:重写之后的方法不能比之前的方法抛出更多的异常,可以更少。

    注意事项:
    注意1:方法覆盖只是针对于方法,和属性无关。
    注意2:私有方法无法覆盖。
    注意3:构造方法不能被继承,所以构造方法也不能被覆盖。
    注意4:方法覆盖只是针对于“实例方法”,“静态方法”覆盖没有意义。

    方法重载和方法覆盖有什么区别?
    方法重载发生在同一个类当中。
    方法覆盖是发生在具有继承关系的父子类之间。
    方法重载是一个类中,方法名相同,参数列表不同。
    方法覆盖是具有继承关系的父子类,并且重写之后的方法必须和之前的方法一致:
    方法名一致、参数列表一致、返回值类型一致。

    方法覆盖的经典案例

    一定要注意:方法覆盖/方法重写的时候,建议将父类的方法复制粘贴,这样比较保险。

    public class Test00{
        public static void main(String[] args){
            //创建一个中国人对象
            ChinesePeople p1 = new ChinesePeople();
            p1.setName("张三");
            p1.speak();
            //创建一个美国人对象
            AmericanPeople p2 = new AmericanPeople();
            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 ChinesePeople extends People{
        //中国人说话时汉语
        //所以子类需要对父类的speak()方法进行重写
        public void speak(){
            System.out.println(this.getName() + "正在说汉语.");
        }
    }
    //美国人类
    class AmericanPeople extends People{
        //美国人说话是英语
        //所以子类需要对父类的speak()方法进行重写
        public void speak(){
            System.out.println(this.getName() + " speak English.");
        }
    }
    

    Object类中的toString()方法

    toString()方法的作用是:将“java对象”转换成“字符串的形式”。

    Object类中toString()方法的默认实现是:
    public String toString(){
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

    toString:方法名的意思是转换成String
    含义:调用一个java对象的toString()方法就可以将java对象转换成字符串的表示形式。

    大多数的java类toString()方法都是需要覆盖的。因为Object类中提供的toString()方法输出的是一个java对象的内存地址。

    toString()方法具体怎么进行覆盖?
    格式可以自己定义,或者听需求(项目要求)的。

    相关文章

      网友评论

        本文标题:Java学习14:继承、方法覆盖

        本文链接:https://www.haomeiwen.com/subject/aemgyktx.html