一篇文章让你了解Java中的继承

继承

一.什么是继承

是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。

二.为什么要使用继承

在日常写代码的过程中,有时会敲写很多重复的代码,让自己的代码冗长无味,降低了可读性。当我们使用继承时,代码就变得简洁明了,更加美观。减少无用代码,提高开发效率。

我们举一个例子来说明:
我们在编写程序时,遇到一类相同的物时,通常需要挨个定义,如下
编写狗类时,我们需要狗拥有名字,年龄,毛色等的属性,也需要eat()等成员方法,以便后续使用
编写猫类时,我们也需要猫拥有名字,年龄,毛色等属性,也同样需要eat()等方法
这时我们发现狗和猫有许多重复的定义(共性)–名字,年龄,eat()等…
那我们可不可以使用一种语法来减少重复呢?这时就发明了继承。

在这里插入图片描述

三.继承的语法

修饰符 class 子类 extends 父类 {
            派生类        基类
                          超类

}

使用关键字extends来构写继承。
以猫和狗为例子,它们都属于动物,所以我将共性的类名称作Animal

//动物类——共性
class Animal{
    public String name;

    public int age;
    public String color;
    public void eat(){
        System.out.println(this.name+"正在吃饭");
    }
}
//狗类
class Dog extends Animal{
    public float weight;
    public void barks(){
        System.out.println(super.name+" 汪汪汪");
    }

}
//猫类
class Cat extends Animal{
    public void sleep(){
        System.out.println(super.name+ " 正在睡觉");
    }
}

四.继承中有重复怎么办?

观察如下代码,我们可以看到在父类中有变量a,而子类中也定义了a。我们在

class Base{
    public int a = 10;
    public int b = 3;
}
class Derived extends Base{
    public int a = 20;
    public int c = 30;
public void menthod(){
    System.out.println(a);
}
}
public class menthod {
    public static void main(String[] args) {
        Derived derived = new Derived();
        System.out.println(derived.a);
    }
}

在这里插入图片描述

1.访问原则

成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。

1.如果访问的成员变量子类中有,优先访问自己的成员变量。
2.如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
3.如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
可以不可以打印出父类a的值? 这时就引出来我们的super和this

五.super和this

1.this

this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

2.super

该关键字主要作用:在子类方法中访问父类的成员。

以上面的代码为例,可以得到这样的一个图解:
在这里插入图片描述

3.super注意事项

1.super不能出现在static修饰的方法。
2.子类在继承父类之后,要使用构造方法将父类成员进行初始化。
3.在子类构造方法中,会默认调用父类的无参构造方法,这是编译器自动添加的。默认是super()。
4.如果父类的构造方法是有参数的,则子类也需要是有参数的
在调用父类时,要先将父类的成员变量初始化

4.super和this异同点

相同点
1:都是关键字。
2:都不能出现在静态构造方法中
3:this()和super()都需要位于构造方法中的第一行,也就意味着this()和super()不能同时出现

不同点
1:this是对当前对象的引用;
2:this符合就近原则访问成员变量,super访问父类成员变量。
3:this()用来调用子类构造方法,super()调用父类构造方法;
4:若存在继承,在子类的构造方法中,一定有super(),若自己不自定义,编译器也会也会自动添加,而this()则没有。

六.构造方法的引入

1.父类不带参数的构造方法

在子类构造方法中,会默认调用父类的无参构造方法,这是编译器自动添加的。默认是super();
我们在实例化对象后,该怎么写就怎么写

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "小黄";
        dog.age = 1;
    }
}

2.父类带有参数的构造方法

这种情况就比较复杂了。蓝色背景的代码为新加入的构造方法。

在这里插入图片描述

观察代码,父类中自己定义了带参数的构造方法,这时我们在定义子类时,一定要先对父类的构造方法进行处理,这种处理通常是在自己的构造方法中默默使用super对父类构造方法进行涵盖,如下:

在这里插入图片描述
在这里插入图片描述
这里我们发现,在父类中使用this,在子类中使用super,这就跟上面解释的this和super的原理有关。
定义好之后,我们该如何使用呢?代码如下

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("小黄",1);
        Cat cat = new Cat("喵喵",2);
        dog.eat();
        cat.sleep();
    }
}

运行效果如下:
在这里插入图片描述

七.继承中的执行顺序

先说结论

1.父类的实例,
2.父类的构造,
3.子类的实例
4.子类的构造。

class Person{
    public String name;
    public int age;
    public Person(String name,int age){
        this.name = name;
        this.age = age;
        System.out.println("构造方法执行");
    }
    {
        System.out.println("实例化代码块执行");
    }
    static {
        System.out.println("静态代码块执行");
    }
}
class Student extends Person{
    public Student(String name,int age) {
        super(name,age);
        System.out.println("Student:构造方法执行");
    }
    {
        System.out.println("Student:实例代码块执行");
    }
    static {
        System.out.println("Student:静态代码块执行");
    }
}
public class testdemo {
    public static void main(String[] args) {
        Student student1 = new Student("张三",19);
        System.out.println("===========================");
        Student student2 = new Student("gaobo",20);


    }
}

在这里插入图片描述
通过分析执行结果,得出以下结论:
1、父类静态代码块优先于子类静态代码块执行,且是最早执行
2、父类实例代码块和父类构造方法紧接着执行
3、子类的实例代码块和子类构造方法紧接着再执行
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

八.继承方式

单继承
在这里插入图片描述
多层继承
在这里插入图片描述
不同类继承同一类
在这里插入图片描述
但是不支持多继承
在这里插入图片描述

时刻牢记, 我们写的类是现实事物的抽象. 而我们真正在公司中所遇到的项目往往业务比较复杂, 可能会涉及到一系列复杂的概念, 都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多. 类之间的关系也会
更加复杂.
但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了

如果想从语法上进行限制继承, 就可以使用 final 关键字

九.final

1:修饰变量,则该变量的值不能再被改变。
2:修饰类,则表示该类不能被继承
3:修饰方法,则该方法不能被重写

十.组合

和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法
(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。

通俗来说就是继承反转过来。

轮胎类
class Tire{
// ...
}
// 发动机类
class Engine{
// ...
}
// 车载系统类
class VehicleSystem{
// ...
}
class Car{
private Tire tire; // 可以复用轮胎中的属性和方法
private Engine engine; // 可以复用发动机中的属性和方法
private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
}

码字不易,感谢观看
如果对你有帮助的话,记得点赞👍评论+关注吧

评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃南瓜的北瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值