super关键字与方法重写

目录

super关键字的基本介绍

基本语法

super关键字细节

super和this的区别

方法重写

基本介绍

方法重写使用事项注意细节

重载和重写的区别


super关键字的基本介绍

基本介绍 :

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

基本语法

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

super.属性名;

2.访问父类的方法,不能访问父类的private方法

super.方法名(参数列表);

3.访问父类的构造器(这点前面用过):

super(参数列表);只能放在构造器的第一句,只能出现一句!

代码演示:

1.在下面的代码中我们可以看到,super(),表示的是去访问父类的中的属性或者方法,如果如果要查找的属性在父类中没有话,那么会去一直向上查找,一直查找到顶级父类Object,如果一直查找不到就会报错

2.使用super关键之去访问父类的属性和方法,也需要遵守访问修饰符的权限

3.如果要希望指定去调用父类的哪一个构造器,那么需要在子类的构造器中,显示的声明一下,否则默认调用的时候,调用的是父类的无参构造器,如果父类的无参构造器被覆盖了,那么在使用子类创建对象的时候,子类的构造器中,就必须指定调用父类的哪一个构造器,否则会编译错误

package com.idea.super_;

/**
 * 演示super关键字的基本使用
 */
public class super01 {
    public static void main(String[] args) {
        //super关键字的作用
        //super代表父类的引用,用于访问父类的属性、方法、构造器

        //基本语法
        //1.访问父类的属性,但不能访问父类的private属性  super.属性名;
        //2.访问父类的方法,不能访问父类的private方法  super.方法名(参数列表);
        //3.访问父类的构造器(这点前面用过):  super(参数列表);只能放在构造器的第一句,只能出现一句!

        Dog dog = new Dog();
        System.out.println();
        Dog dog1 = new Dog("jack");

        //dog.hi();
    }
}

class Animal {//父类
    //私有的名字属性
    private String name;
    //公有的年龄属性
    public int age;

    //有参构造器
    public Animal(String name, int age) {
        System.out.println("父类的有参构造器被调用");
        this.name = name;
        this.age = age;
    }

    //无参构造器
    public Animal() {
        System.out.println("父类的无参构造器被调用");
    }

    public String getName() {
        return name;
    }

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

    public void cry(String name) {
        System.out.println("hello,word" + " " + name);
    }
}

class Dog extends Animal {

    public Dog() {
        //3.访问父类的构造器(这点前面用过):  super(参数列表);只能放在构造器的第一句,只能出现一句!
        super();//表示去访问父类的无参构造器
        //这样是错误的,只能有一个super,并且只能出现在构造器中的第一行,否则会报错
        //super("jack",10);
        System.out.println("子类的无参构造器被调用");
    }

    public Dog(String name){
        super("jack",10);//表示去访问父类的有参构造器
        System.out.println("子类的带一个参数有参构造器被调用");
    }

    public void hi() {
        //1.访问父类的属性,但不能访问父类的private属性  super.属性名;
        //可以访问父类的public属性
        System.out.println(super.age);
        //这样是错误的,不可以访问父类的private属性
        //System.out.println(super.name);
        //如果想要访问父类的私有属性,需要调用父类提供的公共方法
        System.out.println(super.getName());


        //2.访问父类的方法,不能访问父类的private方法  super.方法名(参数列表);
        //使用super去访问父类的方法,同理如果方法是私有的也不能直接访问,需要父类提供公共的方法才可以
        super.cry("jack");


    }
}

super关键字细节

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

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

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

代码演示:

package idea.super_;

/**
 * 演示super关键字的注意事项和使用细节
 */
public class superDetail {
    public static void main(String[] args) {
        //1.调用父类的构造器的好处(分工明确,父类的属性由父类初始化,子类的属性由子类初始化)
        //2.当子类有和父类中的成员(属性和方法)重名是,为了访问父类的成员,必须通过super,通过没有重写,使用super、this 直接方法也是一样的效果
        //3.super的访问不限于父类,如果爷爷类和本类都有同名的成员,也可以使用super去访问爷爷类的成员:如果多个基类(上级类)中都有同名的成员,使用super方法遵守就近原则

        B b = new B();
        b.test();
    }
}

class Base { //父类是Object

    public int n1 = 999;
    public int age = 111;

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

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

class A extends Base {
    //4个属性 不同权限的属性
    //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 cal() {
//        System.out.println("A类的cal() 方法...");
//    }

    //四个不同权限的方法
    public void test100() {
    }

    protected void test200() {
    }

    void test300() {
    }

    private void test400() {
    }
}

class B extends A {

    public int n1 = 888;

    //编写测试方法
    public void test() {
        //super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;
        // 如果多个基类(上级类)中都有同名的成员,使用super访问遵循就近原则。A->B->C

        System.out.println("super.n1=" + super.n1);//super表示去访问父类的成员,因为在我们的父类中n1所以输出的也就是父类中的n1
        System.out.println(this.n1);//如果使用的是this,那么输出的就是本类中的属性,如果本类中没有这个属性,那么就回去父类中查找,规则一样

        super.cal();
    }

    //访问父类的属性 , 但不能访问父类的private属性 [案例]super.属性名
    public void hi() {
        System.out.println(super.n1 + " " + super.n2 + " " + super.n3);
    }

    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类
        // 提示:如果查找方法的过程中,找到了,但是不能访问, 则报错, cannot access
        //      如果查找方法的过程中,没有找到,则提示方法不存在
        //cal();
        this.cal(); //等价 cal()

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

        //演示访问属性的规则
        //n1 和 this.n1 查找的规则是
        //(1) 先找本类,如果有,则调用
        //(2) 如果没有,则找父类(如果有,并可以调用,则调用)
        //(3) 如果父类没有,则继续找父类的父类,整个规则,就是一样的,直到 Object类
        // 提示:如果查找属性的过程中,找到了,但是不能访问, 则报错, cannot access
        //      如果查找属性的过程中,没有找到,则提示属性不存在
        System.out.println(n1);
        System.out.println(this.n1);

        //找n1 (super.n1) 的顺序是直接查找父类属性,其他的规则一样
        System.out.println(super.n1);

    }

    //访问父类的方法,不能访问父类的private方法 super.方法名(参数列表);
    public void ok() {
        super.test100();
        super.test200();
        super.test300();
        //super.test400();//不能访问父类private方法
    }

    //访问父类的构造器(这点前面用过):super(参数列表);只能放在构造器的第一句,只能出现一句!
    public B() {
        //super();
        //super("jack", 10);
        super("jack");
    }
}



super和this的区别

看一张表格

NO 区别点 this super
1 访问属性 访问本类中的属性,如果本类没有此属性则到父类中继续查找 从父类开始查找属性
2 调用方法 访问本类中的方法如果本类中没有此方法则到父类中继续查找 从父类开始查找方法
3 调用构造器 调用本类构造器,必须放在构造器的首行 调用父类构造器,必须放在子类构造器的首行
4 特殊 表示当前对象 子类中访问父类对象

方法重写

基本介绍

简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的那个方法

方法重写使用事项注意细节

1.子类的方法的形参列表,方法名称,要和父类方法的形参列表,方法名称完全一样。

2.子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类比如 父类 返回类型是 Object,子类方法返回类型是String 

3.子类方法不能缩小父类方法的访问权限        public >protected >默认>private

代码演示:

package idea.override_;

/**
 * 演示重写的注意事项和使用细节
 */
public class override01 {
    public static void main(String[] args) {


    }
}

class Animal {
    public void cry() {
        System.out.println("动物在叫");
    }

    public Object hi() {
        return null;
    }

    public Object ok() {
        return null;
    }

    protected void eat() {

    }
}

class Dog extends Animal {
    //1.子类的方法的形参列表,方法名称,要和父类方法的形参列表,方法名称完全一样。
    //怎么理解这句话

    //1. 因为Dog 是 Animal子类
    //2. Dog的 cry方法和 Animal的 cry定义形式一样(名称、返回类型、参数)
    //3. 这时我们就说 Dog的cry方法,重写了Animal的cry方法
    @Override
    public void cry() {
        System.out.println("小狗在叫");
    }

    //2.子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类比如 父类 返回类型是 Object,子类方法返回类型是String
    //因为父类的hi()方法的返回类型是Object ,而子类的hi()方法返回类型是String ,因此这样也构成重写,因为Object是所以类的父类
    @Override
    public String hi() {
        return null;
    }

    //注意如果子类的返回类型,如果不是父类的子类,那么就会报错
    //看演示
//    @Override
//    public String ok() {//这样是错误的,因为String不是Object的子类
//        return null;
//    }


    //3.子类方法不能缩小父类方法的访问权限   public >protected >默认>private
    //父类中的方法访问修饰符是,protected 我们重写之后的方法,访问修饰符,只能是和父类一样,或者比父类的还要大

    //举例
    //这样是正确的,但是只能同时存在一个
    @Override
    public void eat() {

    }
//
//    @Override
//    protected void eat() {
//
//    }

    //这样是错误的,因为缩小了,父类方法的访问权限
//    @Override
//     void eat() {
//
//    }
//    @Override
//    private void eat() {
//
//    }
}

重载和重写的区别

名称 发生范围 方法名 形参列表 返回类型 修饰符
重载(OverLoad) 本类 必须一样 类型个数,或者顺序至少一个不同 无需求 无需求
重写(Override) 父子类 必须一样 相同 子类重写的方法返回的类型和父类返回的类型一致,或者是其子类 子类方法不能缩小父类方法的访问权限

猜你喜欢

转载自blog.csdn.net/weixin_53616401/article/details/129701998