zoukankan      html  css  js  c++  java
  • 继承

    1 继承extends
        1.1 什么是继承,有什么用?
            继承:在现实世界当中也是存在的,例如:父亲很有钱,儿子不用很努力也会很有钱。
            继承的作用:
                基本作用:子类继承父类,代码可以得到复用。(这个不是最重要的,是基本作用。)
                主要(重要)作用:因为有了继承关系,有了后期的方法覆盖和多态机制。
                
        1.2 继承的相关特性
                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类。
                
                7 测试:子类继承父类之后,能使用子类对象调用父类方法吗?
                    可以,因为子类继承了父类之后,这个方法就属于子类了。
                    当然可以使用子类对象来调用。
                
                8 在实际开发中,满足什么条件的时候,我可以使用继承?
                    凡是采用“is a”能描述的,都可以继承
                    例如:
                        Cat is a Animal: 猫是一个动物
                        Dog is a Animal: 狗是一个动物
                        CreditAccount is a Accnount: 信用卡账户是一个银行账户。
                        ....
                        
                    假设以后的开发中有一个A类,有一个B类,A类和B类确实也有重复的代码,那么他们两个之间就可以使用继承吗?
                        不一定,还是要看一看他们之间是否能使用is a来描述。
                    
                    class Customer{ // 客户
                        String name;//名字
                        // setter and getter
                    }
                    
                    class product{ // 商品
                        String name;//名字
                        // setter and getter
                    }
                    
                    class Product extends Customer{
                    
                    }
                    
                    以上的继承就属于很失败的。因为:Product is a Customer, 是有违伦理的。
                    
     
            1.3 任何一个类,没有显示继承任何类,默认继承Object,那么Object类当中有哪些方法呢?老祖宗为我们提供了哪些方法?
                以后慢慢的大家一定要适应看JDK的源代码(多看看牛人写的程序自己才会变成牛人。)
                先模仿后超越。
                java为什么比较好学呢?
                    是因为Java内置了一套庞大的类库,程序员不需要从0开始写代码,程序员可以基于这套庞大的类库进行“二次”开发。(开发速度较快,
                        因为JDK内置的这套库实现了很多基础的功能。)
                        
                    例如:String是SUN编写的字符串类、System是SUN编写的系统类。
                    这些类都可以拿来直接使用。
                
                JDK源代码在什么位置?
                    F:Javajdk-13.0.2(你自己安装JDK的路径下)libsrc.zip
                    xxx.java
                    xxx.class
                    
                String[] args
                System.out.println();
                
                你现在能看懂以下代码了吗?
                System.out.println("Hello World");
                System.out 中,out后面没有小括号,说明out是变量名。
                另外System是一个类名,直接使用类名System.out,说明out是一个静态变量。
                System.out 返回一个对象,然后采用“对象.”的方式访问println方法。
                
            我们研究了以下Object类当中有很多方法,大部分看不懂,其中有一个叫做toString()的,我们进行了测试,发现:
                System.out.println(引用);
                当直接输出一个“引用”的时候,println()方法会先自动调用“引用.toString()”,然后输出toString()方法的执行结果。
     
     
    没有继承的案例:
    /*
        1 思考一下 一下代码是不是有点臃肿了,是不是重复的很多。
            分析一下一下程序有什么问题?代码臃肿。代码没有得到他该有的复用性。
    */
    
    public class ExtendsTest01{
        public static void main(String[] args){
            
            // 创建普通账户
            Account a = new Account();
            a.setActno("11111");
            a.setBalance(1000000);
            System.out.println("用户:" + a.getActno() + "的余额是:" + a.getBalance());
            
            // 创建信用账户
            CreditAccount a1 = new CreditAccount();
            a1.setActno("22222");
            a1.setBalance(-1000000);
            a1.setCredit(100);
            System.out.println("用户:" + a1.getActno() + "的余额是:" + a1.getBalance() + "信誉度为:" + a1.getCredit());
        }
    }
    
    // 银行账户类
    // 银行的属性: 账号、余额
    class Account{
        
        // 属性
        private String actno;
        private double balance;
        
        // 构造方法
        // 无参
        public Account(){
        
        }
        
        // 有参
        public Account(String actno,double balance){
            this.actno = actno;
            this.balance = balance;
        }
        
        // getter and setter 方法  实例方法哦
        public void setActno(String actno){
            this.actno = actno;
        }
        
        public String getActno(){
            return actno;
        }
        
        public void setBalance(double balance){
            this.balance = balance;
        }
        
        public double getBalance(){
            return balance;
        }
        
    }
    
    // 其他类型的账户:信用卡账户
    // 账号、余额、信誉度
    class CreditAccount{
        
        // 属性:
        private String actno;
        private double balance;
        private double credit;
        
        // 构造方法
        public CreditAccount(){
        
        }
        
        public CreditAccount(String actno,double balance,double credit){
            this.actno = actno;
            this.balance = balance;
            this.credit = credit;
        }
        
        // getter and setter 方法  实例方法哦
        public void setActno(String actno){
            this.actno = actno;
        }
        
        public String getActno(){
            return actno;
        }
        
        public void setBalance(double balance){
            this.balance = balance;
        }
        
        public double getBalance(){
            return balance;
        }
        
        public void setCredit(double credit){
            this.credit = credit;
        }
        
        public double getCredit(){
            return credit;
        }
    }

    继承之后的案例:

    // 使用继承机制来解决代码问题
    // 继承也是存在缺点的:耦合度高,父类修改,子类受牵连。
    public class ExtendsTest02{
        public static void main(String[] args){
            
            // 创建普通账户
            Account a = new Account();
            a.setActno("11111");
            a.setBalance(1000000);
            System.out.println("用户:" + a.getActno() + "的余额是:" + a.getBalance());
            
            // 创建信用账户
            CreditAccount a1 = new CreditAccount();
            a1.setActno("22222");
            a1.setBalance(-1000000);
            a1.setCredit(100);
            System.out.println("用户:" + a1.getActno() + "的余额是:" + a1.getBalance() + "信誉度为:" + a1.getCredit());
        }
    }
    
    // 银行账户类
    // 银行的属性: 账号、余额
    class Account{ // 父类
        
        // 属性
        private String actno;
        private double balance;
        
        // 构造方法
        // 无参
        public Account(){
        
        }
        
        // 有参
        public Account(String actno,double balance){
            this.actno = actno;
            this.balance = balance;
        }
        
        // getter and setter 方法  实例方法哦
        public void setActno(String actno){
            this.actno = actno;
        }
        
        public String getActno(){
            return actno;
        }
        
        public void setBalance(double balance){
            this.balance = balance;
        }
        
        public double getBalance(){
            return balance;
        }
        
    }
    
    // 其他类型的账户:信用卡账户
    // 账号、余额、信誉度
    class CreditAccount extends Account{ // 子类
        
        // 属性:
        private double credit;
        
        // 构造方法
        public CreditAccount(){
        
        }
        
        public void doSome(){
            // 错误: actno 在 Account 中是 private 访问控制
            // System.out.println(actno);
            // 间接访问
            // System.out.println(this.getActno());
            System.out.println(getActno());
        }
        
        // getter and setter 方法  实例方法哦
        public void setCredit(double credit){
            this.credit = credit;
        }
        
        public double getCredit(){
            return credit;
        }
    }

    java可以实现多继承吗?的案例:

    class A{
    
    }
    
    class B{
    
    }
    
    class C extends A{
    
    }
    
    class D extends B{
    
    }
    
    /*
        语法错误
        java只允许单继承。不允许多继承。java是简单的。c++支持多重继承。
        c++更接近现实一点。因为在现实世界中儿子同时继承父母两方特征。
        ExtendsTest03.java:17: 错误: 需要'{'
        class E extends A,B{
    */
    //class E extends A,B{
    
    //}
    
    class X{
    
    }
    
    class Y extends X{
    
    }
    
    class M extends X{
    
    }
    
    // 其实这说明了Z是继承了X和Y的。
    // 这样描述:Z直接继承了Y,Z间接继承了X
    class Z extends Y{
    
    }



    子类继承了父类,可以直接调用父类中的方法吗?案例:
    /*
        Z继承了Y
        Y继承了X
        X继承了Object
        
        Z对象具有Object对象的特征(基因)。
        
        Object是所有类的超类。老祖宗。类体系结构中的根。
        java这么庞大的一个继承结构,最顶点是:Object
    *//*
        测试:子类继承父类之后,能使用子类对象调用父类方法吗?
            实际上以上的这个问题问的有点蹊跷!!!!!
            哪里蹊跷?“能使用子类对象调用父类方法”
            本质上,子类继承父类之后,是将父类继承过来的方法归自己所有。
            实际上调用的也不是父类的方法,是他子类自己的方法。(因为继承了,所以就属于他自己的了。)
    */
    public class ExtendsTest04{
        public static void main(String[] args){
            // 创建子类对象
            Cat c = new Cat();
            //调用方法
            c.move();
            // 通过子类对象访问name可以吗?
            System.out.println(c.name);
        }
    }
    
    // 父类
    // class Animal extends Object {
    class Animal{
        // 名字(先不封装)
        String name = "xiaoHua";//默认值不是null,给一个xiaoHua
        // 提供一个动物移动的方法
        public void move(){
            System.out.println(name + "正在移动!");
        }
    }
    
    // Cat子类
    class Cat extends Animal{
        
    }
     

    默认继承Object,Object类中有哪些方法呢?(附Object在JDK中的源代码)案例:

    // 默认继承Object,Object类中有哪些方法呢?
    /*
    
    package java.lang;
    
    import jdk.internal.HotSpotIntrinsicCandidate;
    
    public class Object {
        
            // 注意:当原码当中一个方法以“;”结尾,并且修饰符列表中有“native”关键字
            // 表示底层调用C++写的dll程序(dll动态链接库文件)
        private static native void registerNatives();
        
        // 静态代码块(类加载时执行,而且只执行一次。)
        static {
                // 调用registerNatives()方法。
            registerNatives();
        }
            
            // 无参数构造方法
        @HotSpotIntrinsicCandidate
        public Object() {}
        
            // 底层也是调用C++
        @HotSpotIntrinsicCandidate
        public final native Class<?> getClass();
    
            // 底层也是调用C++
        @HotSpotIntrinsicCandidate
        public native int hashCode();
            
            // equals方法你应该能看懂。、
            // public 公开的
            // boolean 返回值
            // equals 是一个方法名:相等
            // obj 形参
        public boolean equals(Object obj) {
                // 方法体
            return (this == obj);
        }
        
            // 已有对象a,想创建一个和a一模一样的对象,你可以调用这个克隆方法。
            // 底层也是调用C++
        @HotSpotIntrinsicCandidate
        protected native Object clone() throws CloneNotSupportedException;
            
            // 一会我们可以测试一下toString() 方法
            // public 表示公共的。
            // String 是一个返回值类型,toString()方法执行结束后返回一个字符串。
            // toString 这是方法名。
            // () 表示形参个数为0
            
        public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
    
        @HotSpotIntrinsicCandidate
        public final native void notify();
    
        @HotSpotIntrinsicCandidate
        public final native void notifyAll();
    
        public final void wait() throws InterruptedException {
            wait(0L);
        }
    
        public final native void wait(long timeoutMillis) throws InterruptedException;
    
        public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
            if (timeoutMillis < 0) {
                throw new IllegalArgumentException("timeoutMillis value is negative");
            }
    
            if (nanos < 0 || nanos > 999999) {
                throw new IllegalArgumentException(
                                    "nanosecond timeout value out of range");
            }
    
            if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
                timeoutMillis++;
            }
    
            wait(timeoutMillis);
        }
    
        @Deprecated(since="9")
        protected void finalize() throws Throwable { }
    }
    */
    public class ExtendsTest05{
        
        // ExtendsTest05 默认继承Object
        // ExtendsTest05 类当中是有toString()方法的
        // 不过toString()方法是一个实例对象,需要创建对象才能调用。
        
        /*
            public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
        */
        
        public static void main(String[] args){
            // 分析这个代码可以执行吗?
            //ExtendsTest05.toString(); //错误: 无法从静态上下文中引用非静态 方法 toString()
            
            // 先new对象。
            ExtendsTest05 et = new ExtendsTest05();
            String retValue = et.toString();
            
            // 2ff4acd0 可以“等同”看做对象在对内存当中的内存地址。
            // 实际上是内存地址经过你“哈希算法”得出的十六进制的结果。
            System.out.println(retValue);//ExtendsTest05@2ff4acd0
            
            // 创建对象
            Product prd = new Product();
            
            String retValue2 =prd.toString();
            System.out.println(retValue2);//Product@5caf905d
            
            // 以上两行代码能否合并成一行!!!可以
            System.out.println(prd.toString());
            
            // 如果直接输出“引用”呢?????
            // 输出 prd 默认调用prd.toSting()方法
            System.out.println(prd);//Product@5caf905d
            
        }
    }
    
    class Product{
        /*
            public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
        */
    }

    测试案例:

    // 在editplus中的红色字体,表示这个类是SUN的JDK写好的一个类。
    public class Test{
        // 静态变量
        static Student stu = new Student();
        
        // 入口
        public static void main(String[] args){
            Test.stu.exam();
            
            System.out.println("Hello World!");
        }    
    }
    
    class Student{
        // 实例方法
        public void exam(){
            System.out.println("考试。。。。。。");    
        }
    }
  • 相关阅读:
    小G的城堡
    最大公约数与扩展欧几里得算法
    阶乘的逆元
    素数的判断
    快速幂
    重载高精度运算符
    Hello World!
    【JavaScript】7-13 日K蜡烛图 (15分)
    【JavaScript】7-12 两个数的简单计算器 (10分)
    【JavaScript】7-11 分段计算居民水费 (10分)
  • 原文地址:https://www.cnblogs.com/xlwu/p/13057681.html
Copyright © 2011-2022 走看看