java 19.继承

继承

共性抽取

类的继承格式

class 父类 {
}
 
class 子类 extends 父类 {
}

继承的关系:is-a,父类更通用,子类更具体。

java单继承,java不支持多继承,支持多级继承

继承的特性

  • 子类拥有父类非 private 的属性、方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法。
  • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

继承关键字

继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。

extends关键字

在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。

public class Animal { 
    private String name;   
    private int id; 
    public Animal(String myName, String myid) { 
        //初始化属性值
    } 
    public void eat() {  //吃东西方法的具体实现  } 
    public void sleep() { //睡觉方法的具体实现  } 
} 
 
public class Penguin  extends  Animal{ 
}

implements关键字

使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。

public interface A {
    public void eat();
    public void sleep();
}
 
public interface B {
    public void show();
}
 
public class C implements A,B {
}

继承中成员变量的访问特点

在父子类的继承关系中,如果成员变量重名,则创建子类对象时,访问有两种方式:

  1. 直接通过子类对象访问成员变量:等号左边时谁,就优先用谁,没有则向上找

  2. 间接通过成员方法访问成员变量:该方法属于谁,就优先用谁,没有则向上找

示例代码

父类子类都有一个变量num

package extendsDemo;

//父类
public class Fu {
    int num = 10;
    int numFu = 20;

    public void methodFu() {
        System.out.println(num);
    }
}

//子类
package extendsDemo;

public class Zi extends Fu{
    int numZi = 100;
    int num = 200;

    public void methodZi() {
        System.out.println(num);
    }
}

//demo
package extendsDemo;

public class demoFuZi {
    public static void main(String[] args) {
        Fu fu = new Fu();
        Zi zi = new Zi();

        System.out.println(zi.num);  //200
        System.out.println("------------------");
        zi.methodZi();  //200
        zi.methodFu();  //10
    }
}

区分子类方法中重名的三种

父类成员变量:直接写成员变量名

子类成员变量:this.成员变量名

子类方法的局部变量:super.成员变量名

Fu.java

package extendsDemo;

public class Fu {
    int num = 10;
}

Zi.java

package extendsDemo;

public class Zi extends Fu{
    int num = 20;

    public void methodZi() {
        int num = 30;
        System.out.println(num);  //30 局部变量
        System.out.println(this.num);  //20 本类的成员变量
        System.out.println(super.num);  //10 父类的成员变量
    }
}

demoFuZi.java

package extendsDemo;

public class demoFuZi {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.methodZi();
    }
}

继承中成员方法的访问特点

在父子类的继承关系中,创建子类对象,访问成员方法的规则:创建的对象是谁,就优先用谁,如果没有则向上找。

注意事项:无论时成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。

示例代码

Fu.java

public class Fu {
    public void method() {
        System.out.println("执行父类的方法");
    }
}

Zi.java

public class Zi extends Fu{
    public void method() {
        System.out.println("执行子类的方法");
    }
}

demoFuZi.java

public class demoFuZi {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.method();
    }
}

java方法中的覆盖重写

重写:Override 在继承关系中,方法的名称一样,参数列表也一样

重载:OverLoad 在继承关系中,方法的名称一样,参数列表不一样

@Override 写在方法前面,用来检测是不是有效的正确覆盖重写。只是检测,方法是重写的话,不写@Override也是重写的。

子类方法的返回值必须小于等于父类方法的返回值范围

java.lang.object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类

子类方法的权限必须大于等于父类方法的权限修饰符

public > protected > (default) > private

default不是关键字default,而是什么都不写,留空。

覆盖重写应用

设计原则:对于已经投入使用的类,尽量不要进行修改。推荐定义一个新的类,来重复利用其中共性内容,并且添加改动新内容。

示例代码

Fu.java

public class Fu {
    public void call() {
        System.out.println("打电话");
    }
    public void send() {
        System.out.println("发短信");
    }
    public void show() {
        System.out.println("显示号码");
    }
}

Zi.java

public class Zi extends Fu{
    public void show() {
        super.show();  //把父类的show方法拿过来重复利用
        System.out.println("显示姓名");
        System.out.println("显示头像");
    }

}

demoFuZi.java

public class demoFuZi {
    public static void main(String[] args) {
        Fu fu = new Fu();
        fu.call();
        fu.send();
        fu.show();
        System.out.println("---------------");
        Zi zi = new Zi();
        zi.call();
        zi.send();
        zi.show();
    }
}

继承中构造方法的访问特点

  1. 在子类构造方法中有一个默认隐含的“super()”调用父类无参构造方法(不写编译器也会加上),所以一定是先调用父类构造,后执行子类构造。
  2. 可以通过super关键字在子类构造方法中调用父类重载构造。
  3. super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。

总结:子类必须调用父类构造方法,不写则编译器自动加super(),写了则用写的指定的super调用,super只能有一个,还必须是第一个。

示例代码

Fu.java

public class Fu {

    public Fu(){
        System.out.println("父类无参构造");
    }
    public Fu(int num){
        System.out.println("父类有参构造");
    }
}

Zi.java

public class Zi extends Fu{

    public Zi(){
        super();  //在调用父类无参构造方法,编译器会自动加上super()
//        super(10);  //通过super关键字在子类构造方法中调用父类重载构造
        System.out.println("子类构造方法");
    }
}

demoFuZi.java

public class demoFuZi {
    public static void main(String[] args) {
        Zi zi = new Zi();
    }
}

super关键字的三种用法

  1. 在子类的成员方法中,访问父类的成员变量
  2. 在子类的成员方法中,访问父类的成员方法
  3. 在子类的构造方法中,访问父类的构造方法

示例代码

Fu.java

public class Fu {

    int num = 10;
    public void method(){
        System.out.println("父类方法");
    }
}

Zi.java

public class Zi extends Fu{

    int num = 20;
    public void methodZi(){
        System.out.println(super.num);  //子类访问父类成员变量
    }
    public void method(){
        super.method();
        System.out.println("子类调用父类成员方法");
    }
    public Zi(){
        super();  // 3
        System.out.println("子类构造方法调用父类构造方法");
    }
}

demoFuZi.java

public class Zi extends Fu{

    int num = 20;
    public void methodZi(){
        System.out.println(super.num);  //子类访问父类成员变量
    }
    public void method(){
        super.method();
        System.out.println("子类调用父类成员方法");
    }
    public Zi(){
        super();  // 3
        System.out.println("子类构造方法调用父类构造方法");
    }
}

this关键字的三种用法

super关键字用来访问父类内容,而this关键字用来访问本类内容。用法三种:

  1. 在本类的成员方法中,访问本类的成员变量
  2. 在本类的成员方法中,访问本类的另一个成员方法
  3. 在本类的构造方法中,访问本类的另一个构造方法

在第三种用法中要注意:

a. this(...)调用必须是构造方法的第一个语句,唯一一个。

b. super和this两种构造调用,不能同时使用。

示例代码

Fu.java

public class Fu {

    int num = 10;
    public void method(){
        System.out.println("父类方法");
    }
}

Zi.java

public class Zi extends Fu{

    int num = 20;
    //在本类的成员方法中,访问本类的成员变量
    public void showNum(){
        System.out.println(num);
        System.out.println(this.num);
        System.out.println(super.num);
        System.out.println("-----------------");

    }
    //在本类的成员方法中,访问本类的另一个成员方法
    public void methodA(){
        System.out.println("AAA");
    }
    public void methodB(){
        this.methodA();
        System.out.println("BBB");
    }
    //在本类的构造方法中,访问本类的另一个构造方法
    public Zi(){
        this(123);  //本类的无参构造调用本类的有参构造
    }
    public Zi(int n){
        this(1,2);
    }
    public Zi(int n, int m){
//        this();  //错误写法
    }
}

super与this关键字图解
super与this关键字图解

更多学习笔记移步 https://www.cnblogs.com/kknote
原文地址:https://www.cnblogs.com/kknote/p/15318378.html