首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >零基础学Java第十三讲---继承和多态(1)

零基础学Java第十三讲---继承和多态(1)

作者头像
寻星探路
发布2025-12-17 18:26:19
发布2025-12-17 18:26:19
1000
举报
文章被收录于专栏:CSDN博客CSDN博客

一、继承

1、什么是继承?

首先我们要知道,什么是继承。在我们的现实生活中,遗产需要由继承人所继承下去;我们万事万物的基因也要继承给下一代。其实,这就代表了子和父的关系,我们的程序设计中也是如此!!!

2、为什么需要继承

ava中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是现实世界错综复杂,事物之间可能会存在⼀些关联,那在设计程序时就需要考虑。

如:猫和狗,它们都是⼀个动物。

我们用Java语言来进行描述,就会设计出这样的代码:

代码语言:javascript
复制
//Dog.java
public class Dog {
    public int age;
    public String name;
    float weight;
 
    public void eat(){
        System.out.println(name + "在吃饭");
    }

    public void sleep(){
        System.out.println(name + "正在睡觉");
    }

    void Bark(){
        System.out.println(name + "汪汪汪~~~");
    }
}

//Cat.java
public class Cat {
    public int age;
    public String breed;
    public String name;
 
    public void eat(){
        System.out.println(name + "在吃饭");
    }

     public void sleep(){
         System.out.println(name + "正在睡觉");
     }

    void mew(){
        System.out.println(name + "喵喵喵~~~");
    }
}

通过观察上述代码可以发现,猫和狗的类中存在大量重复,如下所示:

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

3、继承的概念

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

如:上面的狗和猫都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用。

上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类或超类,Dog和Cat可以称 为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。

从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态(后面的多态会讲到)。

4、继承的语法

在Java中如果要表示类之间的继承关系,需要借助extends关键字,具体如下:

代码语言:javascript
复制
修饰符class⼦类extends⽗类{
        // ...  
}

我们利用继承对上面2中的代码进行重新设计,如下:

代码语言:javascript
复制
 // Animal.java
 public class Animal{
     String name;
     int age;
 
     public void eat(){
         System.out.println(name + "正在吃饭");
     }
 
     public void sleep(){
         System.out.println(name + "正在睡觉");
     }
 }
 
 // Dog.java
 public class Dog extends Animal{    
     void bark(){
         System.out.println(name + "汪汪汪~~~");
     }
 }
 
 // Cat.Java
 public class Cat extends Animal{   
     void mew(){
         System.out.println(name + "喵喵喵~~~");
     }
 }
 
 // TestExtend.java
 public class TestExtend {
     public static void main(String[] args) {
         Dog dog = new Dog();
         // dog类中并没有定义任何成员变量,name和age属性肯定是从⽗类Animal中继承下来的 
         System.out.println(dog.name);
         System.out.println(dog.age);
         // dog访问的eat()和sleep()方法也是从Animal中继承下来的 
         dog.eat();
         dog.sleep();
         dog.bark();
     }
 }

从上述代码我们可以看到Dog类和Cat类的部分代码重复使用了Animal中的代码。

#注:

(1)子类会将父类中的成员变量或者成员方法继承到子类中

(2)子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了!!!

5、父类成员访问

5.1子类中访问父类的成员变量
5.1.1子类和父类不存在同名成员变量
代码语言:javascript
复制
 public class Base {
     int a;
     int b;
 }
 
 public class Derived extends Base{
     int c;
     public void method(){
         a = 10;    // 访问从⽗类中继承下来的a 
         b = 20;    // 访问从⽗类中继承下来的b 
         c = 30;    // 访问⼦类⾃⼰的c 
     }
 }
5.1.2子类和父类成员变量同名
代码语言:javascript
复制
 public class Base {
     int a;
     int b;
     int c;
 }
 
 public class Derived extends Base{
     int a;              // 与⽗类中成员a同名,且类型相同
     char b;             // 与⽗类中成员b同名,但类型不同
 
     public void method(){
         a = 100;        //访问⽗类继承的a,还是⼦类⾃⼰新增的a?
         b = 101;        //访问⽗类继承的b,还是⼦类⾃⼰新增的b?
         c = 102;        //⼦类没有c,访问的肯定是从⽗类继承下来的c
         // d = 103;     //编译失败,因为⽗类和⼦类都没有定义成员变量b
     }
 }

在子类方法中或者通过子类对象访问成员时:

子类自己有优先访问自己的,如果没有去父类里面找,有就用父类的,都没有报错!!!

5.2子类中访问父类的成员方法
5.2.1成员方法名字不同
代码语言:javascript
复制
 public class Base {
     public void methodA(){
         System.out.println("Base中的methodA()");
     }
 }

 public class Derived extends Base{
     public void methodB(){
         System.out.println("Derived中的methodB()⽅法");
     }

     public void methodC(){
         methodB();       // 访问⼦类⾃⼰的methodB()  
         methodA();        // 访问⽗类继承的methodA() 
         // methodD();     // 编译失败,在整个继承体系中没有发现⽅法methodD()  
     }
 }

成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。

5.2.2成员方法名字相同
代码语言:javascript
复制
 public class Base {
     public void methodA(){
         System.out.println("Base中的methodA()");
     }

     public void methodB(){
         System.out.println("Base中的methodB()");
     }
 }

 public class Derived extends Base{
     public void methodA() {
         System.out.println("Derived中的method()⽅法");
     }

     public void methodB(){
         System.out.println("Derived中的methodB()⽅法");
     }

     public void methodC(){
         methodA();     // 优先访问⼦类中的methodA() 
         methodB();      // 直接访问,则永远访问到的都是⼦类中的methodB(),基类的⽆法访问到 
     }
 }

通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法传递的参数选择合适的方法访问,如果没有则报错;

那么问题来了,如果子类中存在和父类中相同的成员时,如何在子类中访问父类相同名称的成员呢?这就引出了我们的关键字super!!!

6、关键字super

由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,该如何操作?直接访问是无法做到的(直接访问都是子类的),Java提供了super关键字,该关键字主要作用:在子类方法中访问父类的成员。

代码语言:javascript
复制
public class Base {
    int a;
    int b;
    public void methodA(){
        System.out.println("Base中的methodA()");
    }
    
    public void methodB(){
        System.out.println("Base中的methodB()");
    }
 }
 
public class Derived extends Base{
    int a;    // 与⽗类中成员变量同名且类型相同 
    // 与⽗类中methodA()构成重载 
    public void methodA(int a) {
        System.out.println("Derived中的method()⽅法");
    }
   
    // 与基类中methodB()构成重写(即原型⼀致,重写后序详细介绍) 
    public void methodB(){
        System.out.println("Derived中的methodB()⽅法");
    }
    
    public void methodC(){
        // 对于同名的成员变量,直接访问时,访问的都是⼦类的
 
        a = 100;   // 等价于: this.a = 100; 
        b = 101;   // 等价于:this.b = 101; 
        // 注意:this是当前对象的引⽤
 
        // 访问⽗类的成员变量时,需要借助super关键字 
        // super是获取到⼦类对象中从基类继承下来的部分 
        super.a = 200;
        super.b = 201;
 
        // ⽗类和⼦类中构成重载的⽅法,直接可以通过参数列表区分访问⽗类还是⼦类⽅法
 
        methodA();      // 没有传参,访问⽗类中的methodA() 
        methodA(20);    // 传递int参数,访问⼦类中的methodA(int) 

        // 如果在⼦类中要访问重写的基类⽅法,则需要借助super关键字 
        methodB();      // 直接访问,则永远访问到的都是⼦类中的methodA(),基类的⽆法访问到 

        super.methodB(); // 访问基类的methodB() 
    }
 }

#注:

(1)super可以访问父类的成员变量和成员方法

(2)只能在非静态方法中使用

(3)在子类方法中,访问父类的成员变量和方法。

7、子类的构造方法

我们有这样的一串代码:

代码语言:javascript
复制
 public class Base {
     public Base(int a){
         System.out.println("Base():" + a);
     }
 }

 public class Derived extends Base{
     public Derived(){
         System.out.println("Derived()");
     }
 }

 public class Test {
     public static void main(String[] args) {
         Derived d = new Derived();
     }
 }

那么代码为什么会编译错误呢?

事实上,当我们在构造子类对象的时候,需要先调用基类构造方法,然后执行子类的构造方法。所以,我们需要在子类对象构造完成之前,先帮助父类对其中的成员进行初始化。具体方式如下:

代码语言:javascript
复制
 public class Base {
     public Base(int a){
         System.out.println("Base():" + a);
     }
 }

 public class Derived extends Base{
     public Derived(){
         super(10);//此时通过super(参数)的形式 
         System.out.println("Derived()");
     }
 }

 public class Test {
     public static void main(String[] args) {
         Derived d = new Derived();
     }
 }
 //打印结果: 
 Base():10
 Derived()

#注:

(1)通过super(参数)的形式可以调用父类指定的构造方法

(2)super()的形式只能出现在子类的构造方法当中且必须在第⼀行

那下面的代码为什么没有报错呢?

代码语言:javascript
复制
 public class Base {
     public Base(){
         System.out.println("Base()");
     }
 }

 public class Derived extends Base{
     public Derived(){
         // super();   // 注意⼦类构造⽅法中默认会调⽤基类的⽆参构造⽅法:super(),
         // 用户没有写时,默认会添加⼀个super(),⽽且super()必须是⼦类构造⽅法中第⼀条语句 
         // 并且只能出现⼀次 
         System.out.println("Derived()");
     }
 }

 public class Test {
     public static void main(String[] args) {
         Derived d = new Derived();
     }
 }
 //打印结果:
 Base()
 Derived()

#注:当父类的构造方法是不带参数的构造方法且只有这⼀个的情况下,默认会添加⼀个super()。

总结:

由于内容较多,会分为多篇讲解,预知后续内容,请看后续博客!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-11-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、继承
    • 1、什么是继承?
    • 2、为什么需要继承
    • 3、继承的概念
    • 4、继承的语法
    • 5、父类成员访问
      • 5.1子类中访问父类的成员变量
      • 5.2子类中访问父类的成员方法
    • 6、关键字super
    • 7、子类的构造方法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档