Java初阶(继承)

一、什么是继承

把对象的共性抽取出来,放在父类中,子类可以继承父类的内容,这种方式称为 “继承”

二、继承的使用

1.继承了父类中的内容

下面给一个情境:

假如,我们要创建一个两个对象,一个是狗,一个是猫,那么就需要写出一个狗类,一个猫类,而猫类和狗类有一些属性/方法是相同的,为了避免繁琐,我们可以把这些共性抽取出来,把这些共性放在一个名为Animal中,然后猫和狗都去继承Animal的内容。

class Aminal{
    public String name;
    public int age;

    public void eat(){
        System.out.println(this.name + "正在吃饭");
    }
}

class Dog extends Aminal{
    private String color;

    public void bark(){
        System.out.println(this.name + " 正在汪汪叫");
    }
}

class Cat extends Aminal{
    public void bark(){
        System.out.println(this.name + " 正在喵喵叫");
    }
}
public class Main{
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();

        dog.name = "旺财";
        cat.name = "咪咪";
        dog.bark();
        cat.bark();
        dog.eat();
    }
}

在这里插入图片描述

1.解析

由于 brak 方法不是在 Animal 类中定义的,所以属于 Animal 类的对象不能使
用它。然而, 尽管在 Cat、Dog 类中没有显式地定义 eat()方法, 但属于Dog、Cat 类的对象却可以使用它们,这是因为 Dog、Catr 类自动地继承了超类 Animal中的这些方法

2.内部图
在这里插入图片描述

父类中private成员变量虽然在子类中不能直接访问,但是也继承到子类中了

利用继承,人们可以基于已存在的类构造一个新类。继承已存在的类就是复用(继承)这些类的方法和域。在此基础上,还可以添加一些新的方法和域, 以满足新的需求

二、父类的成员访问(super)

原理
Dogr 类不能够直接地访问超类的私有域。也就是说,尽管每个 Dog 对象都拥有一个名为 name 的域, 但在 Dog 类的getName方法中并不能够直接地访问 name 域。只有 Animal 类的方法才能够访问私有部分。如果 Dog 类的方法一定要访问私有域, 就必须借助于公有的接口, Animal 类中的公有方法 getName 正是这样一个接口。

2.1 访问父类的成员变量

  • 父类的成员名和子类的成员名不一致
    • 子类会继承父类的内容
  • 父类的成员名和子类的成员名一致
    • 会优先使用子类成员
    • 如果想要调用的是父类成员,就需要用super
      • 概念:super只是一个关键字,指的是子类继承父类的那块空间,
      • 作用:在子类方法中访问父类的成员或方法
      • 注意
        (1)只能在非静态方法中使用
        (2)必须在子类当中使用,这样才能调用父类的成员或方法
class Father{
    public String name = "父类方法";
    public int age;
}

class Son extends Father{
    public String name = "子类方法";
    public void methodA(){
        System.out.println("调用的是:" + name);
        System.out.println("调用的是:" + super.name);
    }

}

public class Main {
    public static void main(String[] args) {
        Son son = new Son();
        son.methodA();
    }
}

在这里插入图片描述
在这里插入图片描述
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找

2.2 访问父类的成员方法

  • 操作与成员变量类似
class Father{
    public String name;
    public int age;

    public void methodA(){
        System.out.println("调用的是父类中的methodA");
    }

    public void methodB(int a){
        System.out.println("调用的是父类中的methodB");
    }
}

class Son extends Father{
    public void methodA(){
        System.out.println("调用的是子类中的methodA");
    }

    public void methodB(){
        System.out.println("调用的是子类中的methodB");
    }

    public void methodC(){
        super.methodA();
    }
}

public class Main {
    public static void main(String[] args) {
        Son son = new Son();
        son.methodB(5);
        son.methodB();
        son.methodA();
        son.methodC();
    }
}

在这里插入图片描述

  • 注意方法重载

2.3 访问父类的构造方法

  • 因为子类是继承于父类产生的,所以在初始化子类成员前,需要先给父类成员初始化 ----------->使用super给父类初始化
class Father{
    public String name;
    public int age;

    public Father(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class Son extends Father{
    public Son() {
        super("aaa", 19);
    }
}
  • 如果没有主动写构造方法,编译器会自动生成
 public Father() {
    }
    
class Son extends Father{
    public Son() {
        super();
    }
}
  • 无法与this()一起用,因为都要放在第一行

❤️this 和 super 的区别:

  • 相同点
    • 都是Java中的关键字
    • 都不能在静态方法中使用,因为都是依赖于对象的,只能访问非静态的成员 / 方法
    • 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
  • 不同点
    • 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有
    • this指的是引用当前对象中的成员,super相当于是子类对象中从父类继承下来部分成员的引用
      在这里插入图片描述

    三、执行顺序问题

class Father{
    public String name;
    public int age;

    static{
        System.out.println("这是Father的静态代码块");
    }

    {
        System.out.println("这是Father的构造代码块");
    }

    public Father() {
        System.out.println("这是Father的构造方法");
    }

}

class Son extends Father{
    static{
        System.out.println("这是Son的静态代码块");
    }

    {
        System.out.println("这是Father的构造代码块");
    }

    public Son(){
        System.out.println("这是Son的构造方法");
    }
}

public class Main{
    public static void main(String[] args) {
        Son son1 = new Son();
        System.out.println("===============");
        Son son2 = new Son();
    }
}

在这里插入图片描述

  • 静态代码块先执行,并且只执行一次,在类加载阶段执行
    • 父类静态代码块优先于子类静态代码块执行,且是最早执行
    • 第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行
  • 当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后构造方法执行
    • 先执行父类实例代码块和父类构造方法
    • 再执行子类的实例代码块和子类构造方法

四、继承方式 + final

4.1 继承方法

在这里插入图片描述

但是如果出现多个继承关系后,改代码就变成了一件很麻烦的事,所以一般当出现三层继承关系时,我们就可以设置让这个类无法再被继承了。而 final 可以实现这个效果

4.2 final

❤️修饰变量:使得这个变量无法被修改,相当于变成常量,但是需要注意的是,即使是常量,也可以有初始值,只是之后不能再赋值了而已

final class Father{
    
}
/*class Son extends Father{     无法继承,会报错
    
}*/
public class Main{
    public static void main(String[] args) {
        final int a = 0;
        //a = 100;      //会报错
    }
}

❤️修饰类:使得这个无法被继承
final类中的方法,自动变为final方法
❤️修饰方法: 使得方法不能被重写

五、继承与组合

  • 继承是 is - a 的关系,组合是has - a 的关系
    • 子类继承父类,就意味着子类要依赖于父类,灵活性会降低。而且多层继承下来,代码的可维护性会降低。相比之下,组合的灵活性更高,每个对象之间是独立的
    • 一般情况下,遵循【能用组合先用组合】,但是还是要考虑实际情况
  • 面向对象的三种特性是封装、继承、多态,组合不是特性,只是一种实现方式,和继承一样,可以实现代码的复用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值