锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 软件开发
  3. JavaSE——继承和多态详解

JavaSE——继承和多态详解

0
  • 软件开发
  • 发布于 2024-09-19
  • 0 次阅读
黄健
黄健

作者:敲代码の流川枫

博客主页:流川枫的博客

专栏:和我一起学java

语录:Stay hungry stay foolish

工欲善其事必先利其器,给大家介绍一款超牛的斩获大厂offer利器——牛客网

点击免费注册和我一起刷题吧

文章目录

一、继承

1. 如何理解继承?

2. 继承的语法

3. 子类如何访问父类中的成员

3.1 访问成员变量

3.2 访问成员方法

3.3 super关键字

4. 子类构造方法

5. final 关键字

6. 继承与组合

二、多态

1.认识多态

2. 多态实现条件

3. 重写

4. 向上转移和向下转型

向上转型:创建一个子类对象,将其当成父类对象来使用

向下转型:父类引用再还原为子类对象



一、继承

  1. 如何理解继承?

类实例化产生的对象之间可能存在某些关联,继承就是提取这些共性从而达到代码复用


概念:在保持原有类特性的基础上进行扩展,增加新功能,产生新的类的过程,这个类称派生类

继承主要解决的问题是:共性的抽取,实现代码复用

  1. 继承的语法

关键字:extends

格式:

修饰符 class 子类 extends 父类 {

    //... 

}

子类会继承父类的成员变量或者成员方法

子类继承父类后要添加自己特有的成员,即除了父类之外的特性

class Animal{
    public String name;
    public int age;

    public void eat() {
        System.out.println(name+"吃饭");
    }
}
class Dog extends Animal{
    //新加的属性
    public String silly;
    public void houseGuard() {
        System.out.println("看门");
    }
}
class Cat extends Animal {

    //没有添加新属性
    public void catchMouse()  {
        System.out.println(name+"抓老鼠");
    }
}
public class Test {
    public static void main(String[] args) {

        //name和age属性是从父类Animal中继承下来的

        Dog dog = new Dog();
        Cat cat = new Cat();

    }
}

还要注意:Java中不支持多继承,一个子类只能继承一个父类

  1. 子类如何访问父类中的成员

3.1 访问成员变量

成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找

如果找不到,则在父类继承下来的成员变量中寻找要访问的成员变量,找不到编译失败

3.2 访问成员方法

成员方法名字不同:

优先访问自己的,若没有,去访问从父类继承的

成员方法名字相同:

父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,没有则报错

3.3 super关键字

用法:在子类方法中访问父类的成员

class Dog extends Animal{

    public String silly;
    public void houseGuard() {

        System.out.println(super.name+"看门");

    }
}

父类的name没有赋初值,因此是null ,这样就访问到了同名的父类的成员变量

this.会有优先问自己的,没有则访问从父类中继承的

super.直接访问从父类中继承下来的,在子类方法中,如果想要明确访问父类中成员时,借助super关键字即可

总结:

super.data;访问父类的普通成员变量

super.func();访问父类的普通成员方法

super();访问父类的构造方法

注意:上文父类的普通成员方法、变量是指非静态成员方法、变量

  1. 子类构造方法

子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法

看代码:

class Animal{
    public String name;
    public int age;

    //提供一个两个该参数的构造方法
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

    //此处报错
class Dog extends Animal{

    public String silly;
    public void houseGuard() {
        System.out.println(super.name+"看门");
    }
}

对象的初始化需要调用构造方法

添加了带有两个参数的构造器后,编译器不会提供无参的构造方法,因此出现错误

接下来我们看当提供了两个参数的构造方法时如何初始化:

class Dog extends Animal{

    public String silly;
        public Dog(String name, int age, String silly) {

        //先初始化父类部分
            super(name, age);
            this.silly = silly;

        }

        public void houseGuard() {
        System.out.println(super.name+"看门");
    }
}

super(name,age)会先调用父类的构造方法完成初始化

this.silly = silly会完成自己属性的初始化

总结:

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

  2. 父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败

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

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

  1. final 关键字

  2. 修饰变量或字段,表示常量

  3. 修饰类:表示此类不能被继承

String 字符串类, 就是用 final 修饰的, 不能被继承

  1. 修饰方法:表示该方法不能被重写

  2. 继承与组合

与继承相似,组合也是表示类之间关系的方式,能实现代码的复用

继承表示各种类抽象出来的共性,对象之间是is-a的关系

组合(Composition)体现的是整体与部分、拥有的关系,即has-a的关系

例如交通工具车的组合:

class Tire {
    public void run() {
        System.out.println("轮胎转动");
    }
}

class Light {
    public void light() {
        System.out.println("灯亮");
    }
}

public class Vehicle {
    private Tire tire;
    private Light light;

    public Vehicle(Tire tire,Light light) {
        this.tire = tire;
        this.light = light;
    }

    public void operation() {
        light.light();
        tire.run();
    }

    public static void main(String[] args) {
        Tire tire = new Tire();
        Light light = new Light();
        Vehicle vehicle = new Vehicle(tire,light);
        //灯亮
        //轮胎转动
        vehicle.operation();
    }
}

二、多态

1.认识多态

不同的对象在完成某个行为时会产生出不同的状态就叫多态

例如:手机支付时产生的多态

  1. 多态实现条件

  1. 必须在继承体系下

  2. 子类必须要对父类中方法进行重写

  3. 通过父类的引用调用重写的方法

多态体现在:当代码运行时,传递不同类的对象时,会调用对应类中的方法

例如:

class Animal{
    public String name;
    public int age;

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

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

class Dog extends Animal{

    public String silly;

        public Dog(String name, int age, String silly) {
            super(name, age);
            this.silly = silly;
        }
        @Override
        public void eat() {
            System.out.println(name+"吃狗粮");
        }

        public void houseGuard() {
        System.out.println(super.name+"看门");
    }
}
class Cat extends Animal {

    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃猫粮");
    }
    //没有添加新属性
    public void catchMouse()  {
        System.out.println(name+"抓老鼠");
    }
}
public class Test {
    public static void eat(Animal animal) {

        animal.eat;

}
    public static void main(String[] args) {
        Dog dog = new Dog("dog",2,"silly");
        Cat cat = new Cat("cat",3);
        eat(dog);
        eat(cat);

    }
}

Test类中的eat方法参数为Animal,该方法内部并不知道,也不关注当前的a引用指向哪个实例,此时 a这个引用调用 eat方法可能会有多种不同的表现(和 a 引用的实例相关), 这种行为就称为多态

  1. 重写

概念:返回值和形参都不能改变,子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写

重写的好处在于子类可以根据需要,定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法

【方法重写的规则】

子类与父类方法原型一致:返回值类型 方法名 (参数列表) 要完全一致

被重写的方法返回值类型可以不同,但是必须是具有父子关系的

访问权限不能比父类中被重写的方法的访问权限更低,父类方法被public修饰,则子类中重写该方法就不能声明为 protected

父类被static、private修饰的方法、构造方法都不能被重写

@Override注解能帮我们进行一些合法性校验,重写没有构成时报错

  1. 向上转移和向下转型

向上转型:创建一个子类对象,将其当成父类对象来使用

//语法格式:父类类型对象名 = new 子类类型()

    Animal animal = new Cat("cat",2);

使用:

方法一:直接赋值(子类对象赋值给父类对象)

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog("dog",2,"silly");
        Animal animal = dog;
        Animal animal1 = dog;
        Animal animal2 = dog;
    }
}

方法二:方法传参(形参为父类型引用,可以接收任意子类的对象)

    public static void eat(Animal animal) {

        animal.eat;

    }

方法三:方法返回(作返回值:返回任意子类对象)

 public static Animal func(){
        return new Cat("dog",2);
    }

优点:让代码实现更简单灵活

缺陷:不能调用到子类特有的方法

向下转型:父类引用再还原为子类对象

public class Test {
    public static void main(String[] args) {

        Animal animal = new Cat("haha",2);

        if(animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
    }
}

为了提高向下转型的安全性,引入了instanceof,如果该表达式为true,则可以安全转换

” 本期的分享就到这里了, 记得给博主一个三连哈,你的支持是我创作的最大动力!


原文链接: https://blog.csdn.net/chenchenchencl/article/details/126235117

标签: #JAVA 991 #软件开发 1171
相关文章

万字:支付“核心系统”详解 2024-11-02 15:33

专栏作者:隐墨星辰 \| 主编:陈天宇宙 这篇文章也尝试化繁为简,探寻支付系统的本质,讲清楚在线支付系统最核心的一些概念和设计理念。 虽然支付行业已经过了风头最劲的时光,但跨境支付仍然在蓬勃发展,每年依然有很多新人进入这个行业,这篇文章尝试为这些刚入行的新人提供一点帮助。 文章只介绍一些支付行业十几

资深支付架构师视角:实战从问题定义到代码落地的完整套路 2024-11-02 15:33

前言 今天从一个实际案例入手,介绍站在架构师的角度,如何识别并定义问题,提炼需求,技术方案选型,再到详细设计,最后利用AI的能力协助写出核心的代码,验证与调优。 解决问题存在一定的模式,也可以称之为框架,总结出自己的思考和解题框架,以后再碰到同类型的问题就可以如庖丁解牛一样容易。 很多年前,我写代码

Spring 实现 3 种异步接口 2024-10-18 09:07

大家好,我是苏三~ 如何处理比较耗时的接口? 这题我熟,直接上异步接口,使用 Callable、WebAsyncTask 和 DeferredResult、CompletableFuture等均可实现。 但这些方法有局限性,处理结果仅返回单个值。在某些场景下,如果需要接口异步处理的同时,还持续不断地

重学SpringBoot3-集成Redis(五)之布隆过滤器 2024-10-08 11:24

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-集成Redis(五)之布隆过滤器 1. 什么是布隆过滤器? * 基本概念 适用场景 2. 使用 Redis 实现布隆过滤器 * 项目依赖 Redis 配置

设计模式第16讲——迭代器模式(Iterator) 2024-10-08 11:24

一、什么是迭代器模式 迭代器模式是一种行为型设计模式,它提供了一种统一的方式来访问集合对象中的元素,而不是暴露集合内部的表示方式。简单地说,就是将遍历集合的责任封装到一个单独的对象中,我们可以按照特定的方式访问集合中的元素。 二、角色组成 抽象迭代器(Iterator):定义了遍历聚合对象所需的方法

vue2路由和vue3路由区别及原理 2024-10-08 11:24

一、Vue2 与 Vue3 路由的区别 1. 创建路由实例方式的不同 Vue 2 中,通过 Vue.use() 注册路由插件,并通过 new VueRouter() 来创建路由实例。 import Vue from 'vue';import VueRouter from 'vue-router';i

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.