zoukankan      html  css  js  c++  java
  • 继承简介

      继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。继承可以理解为一个对象从另一个对象获取属性的过程。

      如果类A是类B的父类,而类B是类C的父类,我们也称C是A的子类,类C是从类A继承而来的。在Java中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类

      继承中使用的关键字是extends。类的继承决定了一个对象和另一个对象是否是IS-A(是一个)关系。通过继承,我们能实现一个对象获取另一个对象的属性。

     

    一、继承

      通过上面的概述,已经知道了继承,下面通过Code来分析继承:

     

    Animal类:(祖父类)                                                                              
    
    public class Animal {
      public String name = "Animal, 多态成员变量测式,父类对象"; 
      public void show() {
        System.out.println("动物....(祖父类)");
      }
    
      public void eat() {
        System.out.println("动物吃东西....(祖父类)");
      }
    
      public void sleep() {
        System.out.println("动物睡觉....(祖父类)");
      }
    }
    
    Mammal类:(父类)                                                                              
      public class Mammal extends Animal {
        public String name = "Mammal Animal";
        public void fight() {
          System.out.println("哺乳动物喜欢打架吗?...(添加新的功能)");
        }
        public void fly(){
          System.out.println("哺乳动物会飞吗?...(添加新的功能)");
        }
        //测试私有是否可以继承
        private void test() {
          System.out.println("private...");
        }
     
        //测试保护是否可以继承
        protected void test(int a) {
          System.out.println("protected...(被访问了)");
        }
     
        //测试保护是否可以继承
        void test(char c) {
          System.out.println("default...(被访问了)");
        }
    }
    
    Cat类:(子类)                                                                                      
    public class Cat extends Mammal{
      public String name = "Cat";
      public void show() {
        System.out.println("猫...(对父类的重写)");
      }
    }
    
    Dog类:(子类)                                                                                     
    public class Dog extends Mammal{
      public String name = "Dog,验证变量的多态";
      public void show() {
        System.out.println("狗...(子类对父类的重写)");
      }
      public void sleep(){
        System.out.println("狗睡觉...(子类对父类的重写,验证方法的 多态)");
      }
    }
    
    ExtendsDemo类:(测试类)                                                                            
    public class ExtendsDemo {
      public static void main(String[] args) {
        // 验证继承性
        System.out.println("@@@@@@@@@     验证继承性:     @@@@@@@@@");
        Dog dog = new Dog();
        dog.eat();
        // 测试继承的权限
        System.out.println("
    
    @@@@@@@@@     测试继承的权限:     @@@@@@@@@");
        Cat cat = new Cat();
        // 私有的不能访问
        // cat.test();
        // 保护和默认的都可以
        cat.test('c');
        cat.test(1);
        // 子类添加新的功能
        System.out.println("
    
    @@@@@@@@@     子类添加新的功能:     @@@@@@@@@");
        Mammal mammal = new Mammal();
        mammal.fight();
        mammal.fly();
        // 验证重写
        System.out.println("
    
    @@@@@@@@@     验证重写:     @@@@@@@@@");
        Animal animal = new Animal();
        animal.show();
        dog.show();
        // 验证多态性
        System.out.println("
    
    @@@@@@@@@     验证多态性:     @@@@@@@@@");
        // 成员变量的多态验证
        Animal animal2 = new Dog();
        System.out.println(animal2.name);
        System.out.println("成员变量的多态,编译看左边,运行也看左边, 也就是调用的是父类的成员变量
    
    ");
        // 成员方法的多态验证
        animal2.sleep();
        System.out.println("成员方法的多态,编译看左边,运行也看右边, 也就是调用的是子类的成员方法");
      }
    }   

    测试截图:                                                                                                                          

       

    • 继承的父类、子类
    1. 超类:被继承的类叫做超类(父类)。也就是已经存在的类且被定义在某个类的extends关键词后面的类叫做父类
    2. 子类:继承的类叫做子类(基类)。也就是通过超类派生的类
    • 继承的权限
    1. 被private修饰的成员方法和成员变量不能被继承
    2. 被public,protected和默认修饰的成员方法和成员变量能被继承
    • 通过继承子类可以得到超类的非private修饰的方法,如上面Code中的:dog.eat();

    在Dog类中并没有eat()方法,但是却可以调用,是因为Dog继承自Animal,得到了Animal的eat()方法

    • 通过继承也可以得到超类非private修饰的成员变量
    • super关键字 :和this相对,this表示本身对象,而super则是代表超类对象。
    public Dog() {
        super(); //调用父类的构造
    }
    public void sleep() {
        System.out.println("狗睡觉...(子类对父类的重写,验证方法 的多态)");
        super.fly(); //调用父类的方法
     }
    • super和this的总结:
    1. this的三个用途:
      1. 引用隐式参数
      2. 调用该类的其他构造器
    public Dog() {
        this("this测试");
    }
    
    public Dog(String name) {
        super();
        this.name = name;
    }
    1. 调用该类的方法
    2. super的两个用途:
      1. 调用超类的方法
      2. 调用超类的构造器
    • 如果子类没有显示的调用超类的构造器,则将自动调用超类的默认构造器。如果超类没有不带参数的构造器,并且子类构造器中由没有显示的调用超类的其他构造,那么Java编译器将报错。
    • 继承层次:

      对于上面的程序示例,Animal派生Mammal,Mammal派生Dog和Cat,这些继承关系之间就组成了一个层次关系。

      由一个公共超类派生出的所有类的集合被称为继承层次。在继承层次中,从某个特定的类到其祖先的路径被称为继承链。

      图解:

      

     

    二、多态和重写(覆盖)

      多态是对象采取多种形式表现的能力。当一个父类引用是用来指向一个子类对象时,在通过父类对象去调用子类的方法,就是一个多态表现。

    • 多态存在的条件
    1. 继承:多态的存在必须要继承
    2. 重写父类方法:除了继承外,多态还要重写父类的方法
    • 多态是什么?

        多态是指当父类和子类都有同样的方法的时候,且父类对象变量引用了子类的对象,那么在调用的时候,就会动态的绑定到具体的子类,然后在调用子类的这个方法,而不是因为是父类的对象变量就调用父类的方法。

      所以有了a)的两点条件,解释一下:

    1. 继承:因为要父类对象去引用子类的对象,所以要有继承
    2. 重写:因为要有和父类同样的方法,那么这个方法就是继承去的,所  以为了体现不同,最好重写,不然这种多态是无意义的。
    • 多态的实现机制:动态绑定(下面介绍)
    • 多态的三点重点:

        成员变量的多态:编译看左边(看父类),运行看左边(看父类), 所以调用的还是父类的成员对象。

        静态方法的多态:编译看左边(看父类),运行看左边(看父类), 所以调用的还是父类的静态方法。

        成员方法的多态:编译看左边(看父类),运行看右边(看子类), 所以调用的是子类的成员方法。

    • 构造方法的调用:

        在创建子类对象的时候,同时还会调用父类的构造方法,对父类数据进行初始化。

    • 多态的优点
    1. 提高了代码的维护性
    2. 提高了代码的扩展性

     

    三、绑定

      程序绑定的概念:绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定和后期绑定

    • 静态绑定

      在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现。例如:C。针对java简单的可以理解为程序编译期的绑定;这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定

    • 动态绑定

       后期绑定:在运行时根据具体对象的类型进行绑定。若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。

    动态绑定的过程:
    1. 虚拟机提取对象的实际类型的方法表;
    2. 虚拟机搜索方法签名;
    3. 调用方法。 

      

    四、阻止继承

      在实际的开发中可能不允许某个类定义子类,那么这种类叫做最终类或者叫做final类。但这个final类如何实现呢?见下代码就是一个final类:

    final public class Person extends Mammal{
      private String name;
      private String gender;
      private int age;
      public Person(){}
       public Person(String name,String gender, int age){
        super();
        this.name = name;
        this.age = age;
        this.gender = gender;
      }
      ....
    }

     

    扩展知识点:

    • instanceof关键字

      java中的instanceof运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。

    if (dog instanceof Animal) {
      System.out.println("dog是Animal类的一个实例");
    } else {
      System.out.println("dog不是Animal类的一个实例");
    }
    if (animal instanceof Dog) {
      System.out.println("animal是Dog类的一个实例");
    } else {
       System.out.println("animal不是Dog类的一个实例");
    }  

       

      当将超类转成子类之前一定要使用instanceof对子类对象进行检查。如下代码段:

    Animal animal = new Dog();
    if (animal instanceof Dog) {
      Dog dog = (Dog)animal;
      System.out.println("animal是Dog类的一个实例,可以转	换");
    }else {
      System.out.println("animal不是Dog类的一个实例");
    }
    

       

    • 受保护的访问

      受保护的访问就是对protected修饰的方法和成员变量的访问。访问权限见总结12

    • final修饰符(重点)
      1. final修饰变量:那么变量变为常量,在赋初值之后,值不可以在改变
      2. final修饰类:那么类就变为最终类,不可在派生子类
      3. final修饰方法:则该方法可以被继承,但是不可以被重写。
      4. final修饰对象:那么对象的引用不可再变,但是引用对象的值是可以变的。(就  是说对象被final修饰后,就不能在指向其他的对象,但是对  象中存储的值是可以变的)
  • 相关阅读:
    博客访问人数统计
    2018年总结&2019年计划
    区块链产品介绍
    work table a year
    No Ads for Blogs
    滴滴云来袭
    部分博客图片失效问题
    加一个小学期的作品视频
    【原创】我的KM算法详解
    【转载】C++中替代sprintf的std::ostringstream输出流详解
  • 原文地址:https://www.cnblogs.com/geore/p/7157690.html
Copyright © 2011-2022 走看看