0
点赞
收藏
分享

微信扫一扫

Java面向对象编程之继承(包括super关键字详解)

醉东枫 2022-05-03 阅读 68
java

初识继承

继承的概念有点抽象,让我们先看看下面这个例子

package inherit;

public class Animal {
    String name;

    public Animal(String name) {
        this.name = name;
    }

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

class Cat{
    String name;

    public Cat(String name) {
        this.name = name;
    }

    public void eat(String food){
        System.out.println(this.name+"正在吃"+food);
    }
    public void grab(){
        System.out.println(this.name+"捉老鼠");
    }
}

class Bird{
    String name;

    public Bird(String name) {
        this.name = name;
    }

    public void eat(String food){
        System.out.println(this.name+"正在吃"+food);
    }
    public void fly(){
        System.out.println(this.name+"正在飞");
    }


}

可以看出上面的代码存在许多重复的部分,按道理说所有Animal的类都应该具备name属性以及eat这个方法。

那么有没有一种方法可以使bird,cat可以使用animal中的name属性以及eat这个方法呢?

继承就可以实现这种功能

比如,Cat is an Animal,Bird is An Animal,当类和类之间满足一个类is a 另一个类时,一定存在继承关系。此时我们就可以让 Cat 和 Bird 分别继承 Animal 类, 来达到代码重用的效果.

通过继承我们可以将上面的代码进行缩减

package inherit;


class Animal {
    String name;

    public Animal() {
    }

    public Animal(String name) {
        this.name = name;
    }

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

class Cat extends Animal{


    public Cat(String name) {
        this.name = name;
    }

    public void grab(){
        System.out.println(this.name+"捉老鼠");
    }
}

class Bird extends Animal{


    public Bird(String name) {
        this.name = name;
    }

    public void fly(){
        System.out.println(this.name+"正在飞");
    }


}
public class Test {
    public static void main(String[] args) {
        Cat cat=new Cat("猫猫");
        Bird bird=new Bird("小鸟");
        cat.eat("鱼");
        bird.eat("虫");
    }
}

在这里插入图片描述

继承的规则

  • 继承用extends关键字表示:class 子类 extends 父类
  • 一个子类只能继承一个父类(单继承),java中不允许多继承,extands后面只能跟一个父类,允许多层继承
  • 子类会继承父类的所有属性和方法,有显示继承(public 属性和方法可以直接使用),也有隐式继承(private属性和方法),其实子类也继承了这个属性和方法,但是无法直接使用

在这里插入图片描述

明白了继承的规则之后,让我们来思考一个问题,若此时子类和父类中存在同名属性或方法时,访问的到底是子类还是父类呢?

让我们看看下面这段代码

在这里插入图片描述

由此可见当子类与父类属性与方法重名的时候,优先访问子类的属性和方法,当子类中没有这个属性时才会访问父类的

super关键字的使用

看了上面的代码之后,相信你可能会有这样的疑问,当子类与父类属性和方法重名时,若我想访问父类的属性和方法该怎么办?

此时,super关键字就派上用场了

package inherit;


class Base {  // 父类
    int a = 5;
    int b = 100;
    public void method() {
        System.out.println("这是父类的普通方法");
    }
}
class Derived extends Base {  // 子类通过extends关键字继承父类
    int a = 10;
    int c = 1000;
    public void test () {
        System.out.println("当调用子类和父类同名的成员变量a时,默认打印的是:" + this.a);
        System.out.println("当调用子类和父类同名的成员变量a时,使用super关键字打印的是:" + super.a);
    }
}
public class Test3 {
    public static void main(String[] args) {
        Derived derived = new Derived();
        derived.test();
    }
}

在这里插入图片描述

注意:

当有继承关系时this关键字默认再当前类中寻找同名属性,若没找到,继续向上寻找父类中是否有同名属性

super关键字修饰属性

表示从父类中寻找同名属性,上面的代码就展示了这个过程。

若直接父类不存在同名属性再向上寻找

class A{
    int a=6;
}
class B extends A{
    int b=1;
}
class C extends B{
    int a=5;
    public void test(){
        System.out.println(super.a);
    }
}
public class Test2 {
    public static void main(String[] args) {
        C c=new C();
        c.test();

    }
}
//输出6

super关键字修饰方法

  • 修饰构造方法
package inherit;

class Person{
    String name;
    int age;

    public Person() {
        System.out.println("Person的无参构造");
    }
}

class Chinese extends Person{
    public Chinese() {
        //编译器会自动在子类构造函数的第一句加上 super(); 来调用父类的无参构造器
        //此时可以省略不写。如果想写上的话必须在子类构造函数的第一句
        System.out.println("Chinese的无参构造");
    }

}
public class Test4 {
    public static void main(String[] args) {
        Chinese chinese=new Chinese();
    }
}

在这里插入图片描述

注意:当我们要产生一个子类对象时,默认先产生一个父类对象,即调用子类构造方法前默认先调用父类构造方法,通过在子类构造方法的第一行写上super(参数)

package inherit;

class Person{
    String name;
    int age;

   public Person(String name) {
        this.name = name;
        System.out.println("Person的一个有参构造,name是:"+name);
    }
}

class Chinese extends Person{
    public Chinese(String name) {
        super(name);//父类没有无参构造,必须在子类构造方法的第一行,显示地写上super(参数)
        System.out.println("Chinese的有参构造");
    }

}
public class Test4 {
    public static void main(String[] args) {
        Chinese chinese=new Chinese("小明");
    }
}

在这里插入图片描述

注意:若父类不存在无参构造则,子类构造方法的首行必须使用super(有参构造)

  • 修饰普通方法

与修饰属性类似,直接从父类中寻找同名方法

package inherit;

class Person{
    String name;
    int age;

//    public Person() {
//        System.out.println("Person的无参构造");
//    }

    public Person(String name) {
        this.name = name;
        System.out.println("Person的一个有参构造,name是:"+name);
    }
    public void fun(){
        System.out.println("Person的一个普通方法");
    }
}
class Chinese extends Person{

//    public Chinese() {
//        //编译器会自动在子类构造函数的第一句加上 super(); 来调用父类的无参构造器
//        //此时可以省略不写。如果想写上的话必须在子类构造函数的第一句,
//        System.out.println("Chinese的无参构造");
//    }


    public Chinese(String name) {
        super(name);
        System.out.println("Chinese的有参构造");
    }

    public void test(){
        super.fun();//调用父类的普通方法
    }
}
public class Test4 {
    public static void main(String[] args) {
        Chinese chinese=new Chinese("小明");
        chinese.test();
    }
}

在这里插入图片描述

注意:

与this不同,super不能指代当前父类的对象引用

在这里插入图片描述

举报

相关推荐

0 条评论