继承简介

  继承是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修饰后,就不能在指向其他的对象,但是对  象中存储的值是可以变的)
原文地址:https://www.cnblogs.com/geore/p/7157690.html