栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JavaSE-No.7.1——Java的继承(super关键字)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaSE-No.7.1——Java的继承(super关键字)

JavaSE传送门

JavaSE_Start

JavaSE-No.6.2——封装与static

JavaSE-No.6.3——代码块与内部类


注: 关于继承将分成两篇文章讲解,那我们就开始吧~

目录
  • 1. 为什么需要继承
  • 2. 继承的概念
    • 2.1 继承的语法
  • 3 父类成员的访问
    • 3.1 子类访问父类的成员变量和成员方法
    • 3.2 super关键字
  • 4. 子类构造方法
  • 5. super和this的比较


1. 为什么需要继承

Java中使用类对现实世界中实体来进行描述,事物之间可能会存在一些关联,那在设计程序时就需要考虑。

例如: 猫和狗,他们都是动物。

我们分别来定义一个猫类和一个狗类:

class Dog {
    public String name;
    public int age;
    public String color;

    public void eat() {
        System.out.println(name+"正在吃饭!");
    }
    public void walk() {
        System.out.println(name+"正在和主人散步。");
    }
}

class Cat {
    public String name;
    public int age;
    public String color;

    public void eat() {
        System.out.println(name+"正在吃饭!");
    }
    public void play() {
        System.out.println(name+"正在玩球。");
    }
}

我们对比一下,发现两个类有一些相同的成员与方法。

那能否将这些共性抽取呢?面向对象思想中提出了继承的概念,专门用来进行共性抽取,实现代码复用。


2. 继承的概念

那么什么是继承呢?

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

简单来说就是将他们的共性进行抽取,把抽取出来的共性放到一个类当中,我们创建一个Animal类:

class Animal {
    public String name;
    public int age;
    public String color;

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

这时我们会发现Dog类和Cat类都报错了,怎么才能让Dog和Cat类访问到name呢?

2.1 继承的语法

这时我们要用到extends关键字:

修饰符 class 子类 extends 父类 { 
	// ... 
}

更改Dog和Cat类

class Dog extends Animal{

    public void walk() {
        System.out.println(name+"正在和主人散步。");
    }
}

class Cat extends Animal{

    public void play() {
        System.out.println(name+"正在玩球。");
    }
}

我们再来简单解释一下,此处我们的Dog又被称为:子类、派生类;Animal被称为:父类、基类、超类。

我们在主函数中实例化一个dog

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "修勾";
        dog.age = 6;
        dog.color = "white";
        dog.eat();
        dog.walk();
    }
}


总结:

  1. 子类会将父类中的成员变量或者成员方法继承到子类中了
  2. 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了

3 父类成员的访问 3.1 子类访问父类的成员变量和成员方法

子类和父类不存在同名成员变量或成员方法

class Base {
    public int a = 1;
    public int b = 2;
    
    public void func1() {
        System.out.println("父类中func1方法");
    }
}
class Derived extends Base{
    public int c = 3;
    public int d = 4;
    
    public void func2() {
        System.out.println("子类中func2方法");
    }

    public void func() {
        System.out.println(this.a);//访问从父类中继承下来的a,b
        System.out.println(this.b);
        System.out.println(this.c);//访问子类自己的c,d
        System.out.println(this.d);
        this.func1();//调用父类中继承的func1()方法
        this.func2();//调用子类中继承的func2()方法
    }
}

子类和父类成员变量或成员方法同名

class Base {
    public int a = 1;
    public int b = 2;

    public void func1() {
        System.out.println("父类中func1方法");
    }
}
class Derived extends Base{
    public int a = 11;
    public int b = 22;
    
    public void func1(int n) {
        System.out.println("子类中func1方法(n)");
    }
    public void func1() {
        System.out.println("子类中func1方法");
    }

    public void func() {
        System.out.println(this.a);//输出什么??
        System.out.println(this.b);
        this.func1();//输出什么??
        this.func1(1);
    }
}

我们思考一下,此时会输出1、2,还是11、12?会运行父类中的func1还是子类中的func1?

答:11 12,子类中的func1。如果访问的成员变量或成员方法与父类中的同名,则优先访问自己的。

运行结果展示:

# 注意事项 #

  1. 如果访问的成员变量子类中有,优先访问自己的成员变量。如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
  2. 如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
  3. 如果访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
  4. 如果访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错;

3.2 super关键字

如果我们想要在子类父类成员变量和成员方法同名的情况下,想在子类中访问父类这时我们就要用到super关键字

public void func() {
        System.out.println(this.a);//访问子类中的a,b
        System.out.println(this.b);
        System.out.println(super.a);//访问父类中的a,b
        System.out.println(super.b);
        this.func1();//调用子类中的func1方法
        super.func1();//调用夫类中的func1方法
}

运行结果展示:

# 注意事项 #

  1. 只能在非静态方法中使用
  2. 在子类方法中,访问父类的成员变量和方法。
  3. super指代的是子类从父类继承过来的内容这块空间的地址。
  4. super();调用父类的构造方法,接下来就讲到。

4. 子类构造方法

我们回到Animal和Dog类中,我们现在想给Animal提供一个构造方法:

class Animal {
    public String name;
    public int age;
    public String color;
	//新增构造方法
    public Animal(String name,int age,String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

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

这时我们发现,# Dog类报错了 #,我们将其屏蔽,Dog类没有报错。

那么这是为什么呢?

父子父子,先有父再有子,即:子类对象构造时,需要先调用父类构造方法,然后执行子类的构造方法。

我们这里就要在子类的构造中,先对父类进行初始化。

class Dog extends Animal{
    //构造方法
    public Dog(String name, int age, String color) {
        super(name, age, color);//显示的调用父类的构造函数,来初始化此时子类继承过来的父类的属性
    }

    public void walk() {
        System.out.println(name+"正在和主人散步。");
    }
}

# 注意 # super();只能在子类构造方法的第一行。

idea生成

为什么一开始没有写任何构造函数的时候也没有报错呢?

在我们在父类和子类中没有写构造方法时,编译器默认在父类和子类中提供构造方法。

例如: 在Animal类中提供

public Animal() {
        
}

在Dog类中提供

public Dog() {
    super();
}

总结: 子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。

# 注意事项 #

  1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用

  2. 如果父类构造方法只有一个是带有参数的,此时编译器不会再给子类生成默认的构造方法,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。

  3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。

  4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出现


5. super和this的比较

相同点

  1. 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
  2. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在

不同点

thissuper
当前对象的引用,当前对象即调用实例方法的对象子类对象中从父类继承下来部分成员的引用
非静态成员方法访问本类的方法和属性访问父类继承下来的方法和属性
非静态成员方法是一个隐藏参数不是隐藏的参数
构造方法调用本类构造方法调用父类构造方法
构造方法中this(...)用户不写编译器不会自动生成一定会存在super(...)的调用,用户没有写编译器也会增加

(( ◞•̀д•́)◞⚔◟(•̀д•́◟ ))

以上就是今天要讲的内容了,希望对大家有所帮助,如果有问题欢迎评论指出,会积极改正!!关于继承相关的知识还没有结束,下一篇文章会继续讲述,期待大家支持,谢谢~

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/884041.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号