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

目录

  • 继承
    • 一.什么是继承
    • 二.为什么要使用继承
    • 三.继承的语法
    • 四.继承中有重复怎么办?
      • 1.**访问原则**
    • ==五.super和this==
    • 1.**this**
    • 2.**super**
    • 3.**super注意事项**
    • 4.**super和this异同点**
    • 六.构造方法的引入
      • 1.父类不带参数的构造方法
      • 2.父类带有参数的构造方法
    • 七.继承中的执行顺序
    • 八.继承方式
    • 九.final
    • 十.组合

继承

一.什么是继承

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

二.为什么要使用继承

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

我们举一个例子来说明:
我们在编写程序时,遇到一类相同的物时,通常需要挨个定义,如下
编写狗类时,我们需要狗拥有名字,年龄,毛色等的属性,也需要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; // 可以复用车载系统中的属性和方法
// ...
}

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

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2023年12月8日
下一篇 2023年12月8日

相关推荐