Java—面向对象(中)——super关键字、方法重写

目录

一、基本语法

二、super给编程带来的好处/细节

三、super和this的比较

 super课堂讲解代码

四、方法重写/覆盖

1.基本介绍

2.注意事项和使用细节

3.重载和重写的比较



  • 基本介绍

        super代表父类的引用,用于访问父类的属性、构造器、方法。

一、基本语法

        1.访问父类的属性,但不能访问父类的private属性 super.属性名;

        2.访问父类的方法,但不能访问父类的private方法 super.方法名(参数列表);

        3.访问父类的构造器     super(参数列表);只能放在构造器的第一句并且只能出现一句

二、super给编程带来的好处/细节

        1.调用父类构造器的好处(分工明确,父类属性由父类初始化,子类属性由子类初始化)

        2.当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果

        3.super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类(上级类)中都有同名的成员,使用super访问遵循就近原则。

三、super和this的比较

区别点thissuper
访问属性

访问本类中的属性,如果本类没有

此属性则从父类中继续查找        

从父类开始查找属性
调用方法

访问本类中的方法,如果本类没有

此方法则从父类中继续查找

从父类开始查找方法
调用构造器

调用本类构造器,必须放在构造器的首行

调用父类构造器,必须放在

子类构造器的首行

特殊表示当前对象

子类中访问父类对象

(父类的引用)

 super课堂讲解代码

public class super01 {
    public static void main(String[] args) {
        B b = new B();//子类对象
        //b.sum();
        b.Test();
    }
}


public class Base { //父类的父类

    public int n1 = 999;
    public int age = 20;

    public void cal(){
        System.out.println("Base类的cal方法....");
    }
    public void eat(){
        System.out.println("Base类的eat方法....");
    }
}


public class A extends Base{ //父类
    //属性
    public int n1 = 100;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;
    //构造器
    public A(){}
    public A(String name){}
    public A(String name, int age){}
    //方法
    public void test100(){}
    protected void test200(){}
    void test300(){}
    private void test400(){}

    //细节补充代码
    public void cal(){
        System.out.println("A类的cal方法....");
    }
}


public class B extends A{ //子类
    //访问父类的属性,但不能访问父类的private属性 super.属性名;
    public void hi(){
        System.out.println(super.n1 + " " + super.n2 + " " + super.n3);
    }
    //访问父类的方法,但不能访问父类的private方法 super.方法名(形参列表);
    public void ok(){
        super.test100();
        super.test200();
        super.test300();
    }
    //访问父类的构造器 super(参数列表); 只能放在构造器第一句,只能出现一句
    public B(){
        //super();
        super("jack",10);
    }

    //细节补充代码
    public int n1 = 888;
    public void cal(){
        System.out.println("B类的cal方法...");
    }
    public void sum(){
        System.out.println("B类的sum方法....");
        //希望调用父类A的cal方法
        //因为子类B没有cal方法,因此可以使用下面三种方式

        //找cal方法时(cal() 和 this.cal()),顺序如下
//         1.先找本类,如果有,则调用
//         2.如果本类没有,则找父类(如果有,并且可以调用,则调用)
//         3.如果父类没有,则继续找父类的父类,直到找到Object类
//         提示:如果查找方法的过程中找到了,但是不能访问,则报错
//              如果查找方法的过程中没有找到,则提示方法不存在
        //cal();
        //this.cal();//等价与 cal();

        //找cal方法(super.cal())的顺序是直接查找父类,其他规则一样
        super.cal();

        //访问属性的规则与找方法的规则一致
        System.out.println(n1);
        System.out.println(this.n1);
        System.out.println(super.n1);
    }
    //编写测试方法Test
    public void Test(){
        //super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,
        //也可以使用super去访问爷爷类的成员;如果多个基类(上级类)中都有同名的成员,
        // 使用super访问遵循就近原则。A->B->C,当然也要遵守访问权限的相关规则
        System.out.println("super.n1=" + super.n1);
        super.cal();
    }
}

四、方法重写/覆盖

1.基本介绍

        方法重写(覆盖)就是子类有一个方法和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法。当父类中的方法无法满足子类需求或子类具有特有功能的时候,需要方法重写。

        子类可以根据需要,定义特定于自己的行为。既延续了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。

入门案例

public class Animal {
    public String name; // 名字
    public int age; // 年龄

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

    public String getInfo() {
        return "我叫" + name + ",今年" + age + "岁了。";
    }
}


public class Cat extends Animal {
    private String hobby;

    public Cat(String name, int age, String hobby) {
        super(name, age);
        this.hobby = hobby;
    }

    public String getInfo() {
        return "喵!大家好!我叫" + this.name + ",我今年" + this.age + "岁了,我爱吃" + hobby + "。";
    }

    public static void main(String[] args) {
        Animal animal = new Cat("小白", 2, "鱼");
        System.out.println(animal.getInfo());
    }
}

        如上述代码,在 Animal 类中定义了一个返回值类型为 String、名称为 getInfo() 的方法,而 Cat 类继承自该类,因此 Cat 类同样含有与 Animal 类中相同的 getInfo() 方法。但是我们在 Cat 类中又重新定义了一个 getInfo() 方法,即重写了父类中的 getInfo() 方法。在 main() 方法中,创建了 Cat 类的对象 animal,并调用了 getInfo() 方法。

2.注意事项和使用细节

        ①子类方法的形参列表,方法名称要和父类的形参列表、方法名称完全一样

       ②子类方法的返回类型和父类方法的返回类型要一样,或者是父类返回类型的子类。比如:父类返回类型是Object,子类的返回类型是String

        ③子类方法不能缩小父类方法的访问权限(可以相等或者扩大)   

            public→protected→默认→private

3.重载和重写的比较

名称发生范围方法名形参列表返回类型修饰符
重载本类必须相同类型、个数或者顺序至少有一个不同无要求无要求
重写父子类必须相同必须相同

子类重写的方法

返回的类型和父类

返回的类型必须一致,或者是其子类

子类方法不能缩小父类方法的访问范围

方法重写练习题

package com.learn.override;

public class OverrideExercise {
    public static void main(String[] args) {
        //在 main 中,分别创建 Person 和 Student 对象,调用 say 方法输出自我
        Person person = new Person("jack", 10);
        System.out.println(person.say());

        Student student = new Student("smith",18,12345,88.8);
        System.out.println(student.say());
    }
}


//编写一个 Person 类,包括属性/private(name、age),构造器、方法 say(返回自我介绍的字符串)
public class Person {
    //属性
    private String name;
    private int age;
    //构造器
    public Person() {
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //方法
    public String say(){
        return "name=" + name + " age=" + age;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}


//编写一个 Student 类,继承 Person 类,增加 id、score 属性/private,以及构造器,
//定义 say 方法(返回自我介绍的信息)
public class Student extends Person{
    //属性
    private int id;
    private double score;
    //构造器
    public Student() {
    }
    public Student(String name, int age, int id, double score) {
        super(name, age);//调用父类的方法
        this.id = id;
        this.score = score;
    }
    //方法
    public String say(){
        return super.say() + " id=" + id + " score=" + score;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public double getScore() {
        return score;
    }
    public void setScore(double score) {
        this.score = score;
    }
}


版权声明:本文为weixin_61843013原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。