Java语言之继承思想

Java语言之继承思想

一、继承的概念

1、继承的思想

​ 在我们生活中相信大家很熟悉继承这个词了吧。简单说,儿子可以继承的父亲的衣钵。在Java中我们也有继承这一说,我们的继承指的是类与类之间,子类可以继承并且使用父类的成员。换句话说,继承就是多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可,这也是我们继承的核心思想。

2、继承的代码格式

class 子类名 extends 父类名 {} 

extends关键字可以实现类与类的继承,单独的这个类称为父类,基类或者超类;多个类可以称为子类或者派生类。

例如:

public class MyTest {
    public static void main(String[] args) {
        Zi zi = new Zi();
        System.out.println("父类的数字为:"+zi.num);
        zi.show();
    }
}
//父类
class Fu{	
    int num=100;
    public void show(){
        System.out.println("这是一个show方法");
    }
}
//子类继承父类
class Zi extends Fu{
}

运行结果为:
在这里插入图片描述

3、继承的优点

​ 继承的优点:(1)继承可以提高代码的复用性,使多个子类可以共用父类的属性和功能;(2)继承可以提高代码的维护性,使共用的那部分代码便于维护和修改;(3)继承可以让类与类之间产生关系,它是多态的前提。

4、继承的缺点

在我们的代码中很重要的一点就是尽量避免牵连,触一发而动全身,但继承却有一个弊端,那就是增加了代码的耦合性,让类跟类之间产生了关系。在我们软件设计的原则里就要求高内聚,低耦合,所有尽量降低代码的耦合性。所谓高内聚就是一个类单独完成某个功能的能力,而低耦合就是指一个类要完成某个功能,尽量避免去依赖某些类。

二、继承的特点

​ 在Java语言中只支持单继承,不支持多继承,但支持多层体系(继承体系),例如若动物是父类的话,那么狗和猫便是子类,他们可以继承动物所共有的属性和功能。

​ 在Java语言的继承中,子类只能继承父类所有非私有的成员(成员方法和成员变量),父类私有的成员子类不可继承。子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。继承的重要一点就是可以使多个子类共用父类的属性和功能,但若只是为了部分功能而去继承,则会增加类的耦合性,这里耦合性指的是若一个类要完成某个功能,得去依赖某些类。

​ 那么我们到底什么时候使用继承呢?简单说,继承其实体现的是一种关系:“is a(什么是什么的一种)” 的关系。我们可以采用假设法,如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。

比如以下例子:

//创建一个动物类,令这个类作为其他类的父类
public class Animal {
    String name;
    int age;
    public void eat() {
        System.out.println("动物都会吃饭");
    }

    public void sleep() {
        System.out.println("动物都会睡觉");
    }
}

//创建猫类,作为动物类的一个子类
public class Cat extends Animal{
    public void catcheMouse(){
        System.out.println("猫会抓老鼠");
    }
}
//创建狗类,作为动物类的另一个子类
public class Dog extends Animal{
    public void lookDoor() {
        System.out.println("狗可以看门");
    }
}
//创建测试类,进行编译运行
public class MyTest {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.name = "汤姆";
        cat.age = 5;
        System.out.println(cat.name);
        System.out.println(cat.age);
        cat.sleep();
        cat.eat();
        cat.catcheMouse();
        System.out.println("----------------------");
        Dog dog = new Dog();
        dog.name = "旺财";
        dog.age = 10;
        System.out.println(dog.name);
        System.out.println(dog.age);
        dog.sleep();
        dog.eat();
        dog.lookDoor();
    }
}

运行结果为:
在这里插入图片描述

三、继承中成员的关系

1、继承中成员变量的关系

​ 在继承中若子类中的成员变量和父类中的成员变量名称一样时,则在子类中访问一个变量就会遵循就近原则,所谓就近原则,就是代码运行时虚拟机会先在子类方法的局部范围找,有便会使用;若没有,则会在子类的成员范围找,有便会使用;若仍然没有,子类便会在父类的成员范围找,有便使用;若还找不到,系统就会报错。

2、继承中成员方法的关系

​ 其实继承中的成员方法与继承中的成员变量原理是一样的。在继承中若子类中的成员方法和父类中的成员方法名称一样时,则通过子类调用这个方法也会遵循就近原则,即代码运行时虚拟机会先查找子类中有没有该方法,如果有就使用;若没有,则再看父类中有没有该方法,有便会使用;若还查找不到,系统便会报错。

3、继承中构造方法的关系

​ 在继承中子类所有的构造方法默认都会访问父类中空参数的构造方法。因为子类会继承父类中的数据,可能还会使用父类的数据。所以,先要使父类的构造方法执行,完成对父类数据的初始化,然后再完成自己的数据的初始化。其实,在每一个构造方法的第一条语句默认都是super(),super关键字可以调用父类的空参构造,完成父类数据的初始化。而在其他还没有类的继承的构造方法体里面,其第一条语句默认都是object(),Object是所有类的顶层父类,所有类都是直接或简介继承自他,object关键字可以操作所有的还没有明确类的继承的类,可以对此类进行初始化操作。

例如下面的例子:

public class MyTest {
    public static void main(String[] args) {
        new Zi();	//调用子类的空参构造方法
        System.out.println("--------------------");
        new Zi(10);		//调用子类的有参构造方法
    }
}
class Fu{
    int num=10;
    public Fu() {
        super();
        System.out.println("父类的空参构造执行了");
    }
    public Fu(int num) {
        super();
        this.num = num;
        System.out.println("父类的有参构造执行了");
    }
}
class Zi extends Fu{
    int num=100;
    public Zi() {
        super();

        System.out.println("子类的空参构造执行了");
    }
    public Zi(int num) {
        super();
        System.out.println("子类的有参构造执行了");
    }
}

运行结果为:
在这里插入图片描述
​ 那么问题来了,若子类有空参构造方法而父类没有空参构造方法,子类怎么办呢?

​ 解决办法有两种,第一种是我们可以直接在父类中添加一个无参的构造方法便可,第二种是子类可以通过this去调用本类的其他有参构造方法,然后在本类的有参构造方法中通过super去调用父类其他的有参构造方法,但是注意一点,super(…)语句或者this(….)语句必须出现在第一条语句上。

例如下面的例子:

public class MyTest {
    public static void main(String[] args) {
        new Zi();
        System.out.println("--------------------");
        new Zi(10);
    }
}
class Fu{
    int num=10;
    public Fu(int num) {
        super();
        this.num = num;
        System.out.println("父类的有参构造执行了");
    }
}
class Zi extends Fu{
    int num=100;
    public Zi() {
        this(20);
        System.out.println("子类的空参构造执行了");
    }
    public Zi(int num) {
        super(num);
        System.out.println("子类的有参构造执行了");
    }
}

运行结果为:
在这里插入图片描述
​ 若父类和子类都没有空参构造方法呢?

解决办法依然有两种,第一种是我们可以直接在子类和父类中添加一个无参的构造方法便可,第二种是在子类的有参构造方法中直接通过super调用父类的余灿构造方法即可。

四、继承中的方法重写

1、方法重写概述

​ 方法重写就是在父类与子类有继承的情况下,子类会出现和父类一模一样的方法,方法中的方法名、参数列表、返回值类型都一样,便会发生子类的方法覆盖父类的方法,这样的现象就叫方法重写。比如说,当子类需要父类的功能,但功能主体子类又有自己特有的内容时,我们便可在在子类重新声明与父类一模一样的方法,这样的操作便是重写父类中的方法。这样,既沿袭了父类的功能,又定义了子类特有的内容。

2、方法重写的应用

​ 方法重写需要注意以下几点内容,子类重写父类的方法时,建议在声明时最好一模一样,以便体现代码的可读性和规范性;父类中的私有方法不能被重写,因为子类无法继承父类的私有方法,所以也就没有父类私有方法重写这一说了;子类在重写父类的方法时,访问权限(权限修饰符)不能比父类的访问权限低,建议最好写的一致,这样便不容易出错;子类在声明和父类一模一样的静态方法时,此时便不算静态方法重写,只能说明子类拥有这个静态方法。

五、继承中的this关键字与super关键字

1、this关键字

​ 其实在构造方法中我们就用到了this关键字,this关键字代表的是本类对象的引用,可理解为本类的一个对象,哪个对象调用这个方法,方法中的this就代表这个对象。this关键字的使用场景: this关键字可以调用本类的成员变量; this关键字可以调用本类的成员方法;this关键字可以调用本类的构造方法。

2、super关键字

super关键字代表的是父类存储空间的标识,可理解为父类的引用,可操作父类的成员,即使用super去访问父类的数据(成员变量、成员方法、构造方法)。super关键字的使用场景: super关键字可以调用父类的成元变量;super关键字可以调用父类的成员方法;super关键字可以调用父类的构造方法。

猜你喜欢

转载自blog.csdn.net/changjinfeng123/article/details/89374974