java 之 继承与多态的详细介绍

news2024/11/27 14:39:21

在这里插入图片描述

文章目录

  • 类的继承
      • 1. 基本语法
      • 2. 继承的特点
      • 3. 方法的重写(方法的覆盖)
      • super 关键字
      • 1. 调用父类的构造器
      • 2. 访问父类的成员变量
      • 3. 调用父类的方法
      • 4. 在构造器中调用父类方法
      • 封装性以及访问修饰符
      • 抽象方法
      • 1. 声明抽象类
      • 2. 抽象方法
      • 3. 继承抽象类
      • 4. 抽象类的实例化
      • 5. 构造器和抽象类
      • 6. 抽象类 vs 接口
      • 子类对象与父类对象的转换
      • 1. 向上转型(Upcasting)[自动转换]
      • 2. 向下转型(Downcasting)[强制转换]
        • 差异
          • 1. `Animal myAnimal = new Dog();`
          • 2. `Dog myAnimal = new Dog();`
          • 总结
      • instanceof 运算符
      • 语法
      • 示例
      • 应用场景
      • 多态与重载

类的继承

在Java中,类的继承是一种重要的面向对象编程(OOP)概念,它允许一个类(子类)继承另一个类(父类)的属性和方法。这种机制使得代码可以更加灵活、可复用,并支持多层次的类之间的关系。以下是关于Java中类的继承的详细介绍:

1. 基本语法

在Java中,使用关键字 extends 实现类的继承。语法如下:

class Subclass extends Superclass {
    // 子类的成员变量和方法
}

其中,Subclass 是子类,Superclass 是父类。

2. 继承的特点

  • 单一继承: Java不支持多继承,一个子类只能继承一个父类。这是为了避免多继承可能引发的复杂性和歧义。

  • 构造器的继承: 子类会继承父类的构造器,但是子类的构造器不能直接调用父类的构造器。在子类的构造器中,可以使用 super 关键字调用父类的构造器。

  • 访问权限: 子类可以访问父类中的公有(public)和受保护(protected)的成员,但不能访问私有(private)的成员。

3. 方法的重写(方法的覆盖)

子类可以重写(override)父类中的方法,以满足子类的需求。重写的方法必须具有相同的方法签名(方法名字,参数列表、返回类型),而且访问权限不能比父类中的方法更严格。

class Superclass {
    void display() {
        System.out.println("Superclass display");
    }
}

class Subclass extends Superclass {
    @Override
    void display() {
        System.out.println("Subclass display");
    }
}
  • 注意父类中的private 方法不能被被覆盖,父类中的static 方法能被继承,不能被覆盖

super 关键字

在Java中,super 是一个关键字,用于引用父类的成员变量、方法或构造器。它可以用于以下几种情况:

1. 调用父类的构造器

在子类的构造器中,使用 super 调用父类的构造器。这通常用于在子类的构造过程中执行一些父类的初始化操作。

class Superclass {
    Superclass(int x) {
        // 父类构造器
    }
}

class Subclass extends Superclass {
    Subclass(int x, int y) {
        super(x); // 调用父类的构造器
        // 子类构造器
    }
}

2. 访问父类的成员变量

使用 super 关键字可以在子类中访问父类中的成员变量,尤其是当子类和父类有同名的成员变量时。

class Superclass {
    int x = 10;
}

class Subclass extends Superclass {
    void display() {
        System.out.println(super.x); // 访问父类的成员变量
    }
}

3. 调用父类的方法

在子类中,可以使用 super 关键字调用父类的方法。这在子类重写父类方法的时候很有用,可以在子类方法中调用父类版本的方法。

class Superclass {
    void display() {
        System.out.println("Superclass display");
    }
}

class Subclass extends Superclass {
    @Override
    void display() {
        super.display(); // 调用父类的display方法
        System.out.println("Subclass display");
    }
}

4. 在构造器中调用父类方法

在子类的构造器中,可以使用 super 调用父类的方法,确保在子类对象初始化时执行必要的父类操作。

class Superclass {
    void init() {
        // 父类初始化操作
    }
}

class Subclass extends Superclass {
    Subclass() {
        super(); // 调用父类的构造器
        super.init(); // 调用父类的方法
        // 子类构造器
    }
}

总的来说,super 关键字提供了一种访问父类成员的途径,可以在子类中调用父类的构造器、成员变量和方法,从而实现更灵活的代码编写。

封装性以及访问修饰符

Java中封装性的实现主要靠包的实现以及类以及类的成员的访问修饰符来实现
在这里插入图片描述

封装的目的是将对象的状态(成员变量)和行为(方法)封装在一起,提供一种受控的访问机制,防止外部直接访问对象的内部细节。在Java中,封装通过以下方式实现:

  1. 成员变量私有化(Private Fields): 将类的成员变量声明为私有,只能在类的内部访问。

    public class MyClass {
        private int myField;
    
        public int getMyField() {
            return myField;
        }
    
        public void setMyField(int value) {
            // 可以在setter方法中添加一些逻辑,例如范围检查
            if (value >= 0) {
                myField = value;
            }
        }
    }
    
  2. 提供公共方法(Public Methods): 通过公共方法来访问和修改私有成员变量,以实现对成员变量的控制和封装。

    MyClass obj = new MyClass();
    obj.setMyField(42);
    int value = obj.getMyField();
    

通过这种方式,封装隐藏了对象的内部细节,使得对象更加安全、可维护,同时提供了一种更灵活的方式来管理对象的状态。

Java提供了几种访问修饰符,用于控制类、变量、方法等成员的访问权限。

  1. public(公共): 修饰的成员对所有类可见,无访问限制。

  2. private(私有): 修饰的成员只能在当前类中访问,其他类无法直接访问。

  3. protected(受保护): 修饰的成员对同一包内的类和所有子类可见,但对其他包中的类不可见。

  4. default(默认,无修饰符): 修饰的成员对同一包内的类可见,但对其他包中的类不可见。在没有显式声明修饰符的情况下,默认为包内可见。

  5. final(最终): 用于修饰类、方法、变量。修饰类时,表示该类不能被继承;修饰方法时,表示方法不能被重写;修饰变量时,表示变量为常量,不可被修改。

使用访问修饰符和封装的概念,可以控制对象的访问权限,提高代码的安全性和可维护性。

抽象方法

在Java中,抽象类是一种不能被实例化的类,用于定义一些抽象的方法,这些方法在具体的子类中被实现。抽象类通过关键字 abstract 来声明。以下是关于Java抽象类的一些重要概念和规则:

1. 声明抽象类

使用 abstract 关键字来声明抽象类。抽象类可以包含抽象方法和非抽象方法。

abstract class Shape {
    // 抽象方法
    abstract void draw();

    // 非抽象方法
    void display() {
        System.out.println("Displaying shape");
    }
}

2. 抽象方法

抽象方法是没有具体实现的方法,它只有方法签名而没有方法体。任何包含抽象方法的类必须被声明为抽象类。

abstract class Animal {
    abstract void makeSound();
}

3. 继承抽象类

如果一个类继承了一个抽象类,它必须实现父类中所有的抽象方法,否则这个类也必须声明为抽象类。

class Circle extends Shape {
    // 实现抽象方法
    void draw() {
        System.out.println("Drawing circle");
    }
}

4. 抽象类的实例化

抽象类不能被实例化,但可以通过创建其非抽象子类的实例来使用抽象类。例如:

Shape shape = new Circle();
shape.draw();     // 调用子类实现的抽象方法
shape.display();  // 调用抽象类中的非抽象方法

5. 构造器和抽象类

抽象类可以有构造器,但它不能被直接实例化。构造器通常被子类调用,以初始化抽象类中的成员变量。

abstract class AbstractClass {
    AbstractClass() {
        // 构造器
    }
}

6. 抽象类 vs 接口

抽象类和接口都是实现代码重用和多态性的机制,但它们有一些区别。主要的区别在于:

  • 抽象类可以包含非抽象方法,而接口中的方法都是抽象的。
  • 类只能继承一个抽象类,但可以实现多个接口。
abstract class AbstractClass {
    abstract void method1();
    void method2() {
        // 非抽象方法
    }
}

interface MyInterface {
    void method1();
    void method3();
}

抽象类在设计一些具有共同特征的类时非常有用,而接口更适用于定义一些类似于协议的东西,可以被多个类实现。选择抽象类还是接口取决于具体的设计需求。

子类对象与父类对象的转换

在Java中,子类对象与父类对象之间的转换通常涉及向上转型和向下转型,这是基于类的继承关系的一种操作。

1. 向上转型(Upcasting)[自动转换]

向上转型是将子类对象引用赋给父类对象引用的过程,这是一种隐式的转换,不需要显式的类型转换。向上转型是安全的,因为子类对象可以被视为父类对象。

class Animal {
    // ...
}

class Dog extends Animal {
    // ...
}

Dog myDog = new Dog();
Animal animal = myDog; // 向上转型

在这个例子中,myDogDog 类的对象,通过向上转型,可以将它赋给 Animal 类型的引用变量 animal

2. 向下转型(Downcasting)[强制转换]

向下转型是将父类对象引用转换为子类对象引用的过程,这需要使用显式的类型转换,并且在进行转换之前需要确保原始对象是目标子类的实例。

Animal animal = new Dog();
Dog myDog = (Dog) animal; // 向下转型

在这个例子中,animalAnimal 类的对象,通过向下转型,将其转换为 Dog 类型的引用变量 myDog。需要注意,如果在运行时 animal 不是 Dog 类型的对象,将会抛出 ClassCastException 异常。因此,在进行向下转型之前,通常应当使用 instanceof 运算符来检查对象的类型。

if (animal instanceof Dog) {
    Dog myDog = (Dog) animal; // 向下转型
}

向上转型和向下转型的操作在处理多态性和继承关系时是常见的,但需要谨慎使用,以确保类型转换的安全性。

差异

这两行代码涉及到Java中的多态性和引用类型的概念。让我们逐一解释这两行代码的区别:

1. Animal myAnimal = new Dog();

这是一个典型的向上转型(Upcasting)的例子。在这里,创建了一个 Dog 类的对象,并将其赋给了一个 Animal 类型的引用变量 myAnimal

这种向上转型的效果是,尽管 myAnimal 的静态类型(声明类型)是 Animal,但在运行时,它引用的是一个 Dog 对象。这使得你可以通过 myAnimal 调用 Animal 类中定义的方法,但不能调用 Dog 类中独有的方法,除非进行强制类型转换。

Animal myAnimal = new Dog();
myAnimal.someMethod();  // 可以调用 Animal 类的方法
// myAnimal.bark();  // 不能调用 Dog 类的方法,因为其静态类型是 Animal
2. Dog myAnimal = new Dog();

这是一个直接创建 Dog 类的对象,并将其赋给了一个 Dog 类型的引用变量 myAnimal。这是一个常规的对象创建和引用赋值的操作。

在这种情况下,myAnimal 的静态类型和运行时类型都是 Dog。因此,你可以直接调用 Dog 类中定义的方法。

Dog myAnimal = new Dog();
myAnimal.someMethod();  // 可以调用 Animal 类的方法
myAnimal.bark();       // 可以调用 Dog 类的方法
总结
  1. Animal myAnimal = new Dog(); 表示使用 Animal 类型的引用指向 Dog 类型的对象,发生了向上转型。
  2. Dog myAnimal = new Dog(); 表示使用 Dog 类型的引用指向 Dog 类型的对象。

在实际应用中,选择使用哪种方式主要取决于代码的设计需求。向上转型通常用于提高代码的灵活性,而直接使用具体类型的引用则可能更加直观和明确。

instanceof 运算符

instanceof 是Java中的一个二元运算符,用于在运行时检查对象是否是特定类的实例,或者是否实现了特定的接口。它返回一个布尔值,表示对象是否是指定类型的实例。

语法

object instanceof type

其中,object 是要检查的对象,type 是要检查的类或接口的类型。

示例

class Animal {
    // ...
}

class Dog extends Animal {
    // ...
}

class Cat extends Animal {
    // ...
}

Animal myAnimal = new Dog();

if (myAnimal instanceof Dog) {
    System.out.println("myAnimal is an instance of Dog");
} else if (myAnimal instanceof Cat) {
    System.out.println("myAnimal is an instance of Cat");
} else {
    System.out.println("myAnimal is not an instance of Dog or Cat");
}

在这个例子中,myAnimalAnimal 类型的引用,但它指向的是 Dog 类的实例。通过使用 instanceof 运算符,我们可以在运行时检查 myAnimal 是否是 Dog 类或 Cat 类的实例。

应用场景

  1. 类型检查: 用于检查对象是否属于特定的类或接口。

    if (myObject instanceof MyClass) {
        // 执行特定的逻辑
    }
    
  2. 避免 ClassCastException: 在进行向下转型时,先使用 instanceof 进行类型检查,以确保对象是目标类型的实例,避免抛出 ClassCastException 异常。

    if (myObject instanceof Dog) {
        Dog myDog = (Dog) myObject; // 向下转型
        // 执行特定的逻辑
    }
    

instanceof 在面向对象的程序设计中是一个非常有用的工具,能够增加程序的灵活性和鲁棒性,避免在运行时发生类型不匹配的错误。

多态与重载

多态和重载是两个不同的概念。

  1. 多态性(Polymorphism): 多态是指同一个方法调用可以根据对象的不同类型而具有不同的行为。它主要通过方法的’重写(override)‘实现以及方法重载,使得子类能够提供对方法的自定义实现。多态性通过继承和接口的方式来体现,能够提高代码的灵活性和可扩展性。

    class Animal {
        void makeSound() {
            System.out.println("Some generic sound");
        }
    }
    
    class Dog extends Animal {
        @Override
        void makeSound() {
            System.out.println("Bark");
        }
    }
    
    class Cat extends Animal {
        @Override
        void makeSound() {
            System.out.println("Meow");
        }
    }
    
    Animal myDog = new Dog();
    Animal myCat = new Cat();
    
    myDog.makeSound();  // 调用 Dog 类的 makeSound 方法
    myCat.makeSound();  // 调用 Cat 类的 makeSound 方法
    
  2. 重载(Overloading): 重载是指在同一个类中,可以定义多个方法,它们具有相同的名称但是参数列表不同。重载通过方法的参数类型、参数个数或者参数顺序的不同来区分不同的方法。

    class Calculator {
        int add(int a, int b) {
            return a + b;
        }
    
        double add(double a, double b) {
            return a + b;
        }
    }
    
    Calculator myCalculator = new Calculator();
    int resultInt = myCalculator.add(3, 5);        // 调用 int add(int a, int b)
    double resultDouble = myCalculator.add(3.0, 5.0);  // 调用 double add(double a, double b)
    

总结:

  • 多态性是面向对象编程中的一个概念,与继承和接口有关,通过方法的重写与重载实现。
  • 重载是指在同一个类中定义多个方法,它们有相同的名称但参数列表不同,通过参数的类型、个数或者顺序的不同来区分。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1296054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

继承与派生(2)

1.派生类的权限:派生类的成员函数可以访问基类的public和protected类型的成员,而派生类的对象只能访问public类型的成员 2.创建顺序(先创造后析构):基类函数,派生类函数,组合类函数 类的组合按…

12v转48v升压电源芯片:参数、特点及应用领域

12v转48v升压电源芯片:参数、特点及应用领域 随着电子设备的日益普及,电源芯片的需求也在不断增长。今天我们将介绍一款具有广泛应用前景的升压电源芯片——12v转48v升压电源芯片。该芯片具有宽输入电压范围、高效率、固定工作频率等特点,适…

ShardingSphere 使用distinct或者GROUP BY 报类强转的错

ShardingSphere 使用distinct或者GROUP BY 报错 distinct 使用sharding-sphere分表后 对于使用distinct 会报错 类型对象属性转化异常 ,但是去掉DISTINCT后 成功运行 无报错 返回结果正常 但是没有了去重 SELECT DISTINCTlog.* FROMwork_log log,work_log_visi…

网络运维与网络安全 学习笔记2023.12.1

网络运维与网络安全 学习笔记 第三十二天 今日目标 ACL原理与类型、基本ACL配置、高级ACL配置 高级ACL之ICMP、高级ACL之telnet ACL原理与类型 项目背景 为了企业的业务安全,要求不同部门对服务器有不同的权限 PC1不能访问Server PC2允许访问Server 允许其他所…

【C语言】网络字节序和主机字节序

网络字节序和主机字节序是计算机中字节的两种排序方式,它们主要用于解决不同计算机之间数据通信的问题。 一、网络字节序 也被称为大端字节序,是一种标准的字节序。在网络通信中,如果两台主机的字节序不同,可能会导致数据解释的二…

使用命令行移除VSAN中故障磁盘

原创作者:运维工程师 谢晋 使用命令行移除VSAN中故障磁盘 前提故障盘移除 前提 客户有套VSAN环境内有一台服务器的磁盘组出现了一块故障的数据盘,但该盘已经处于完全掉线状态,无法进行正常移除。如下图: 如果遇到这种情况&am…

电子眼+无人机构建平安城市视频防控监控方案

电子眼(也称为监控摄像机)可以通过安装在城市的不同角落,实时监控城市的各个地方。它们可以用于监测交通违法行为、监控公共场所的安全以及实时监测特定区域的活动情况。通过电子眼的应用,可以帮助警方及时发现并响应各类安全事件…

Linux文件系统与基础IO

文章目录 1 C文件接口1.1 fopen1.2 fwrite、fread、rewind、fclose 2 文件系统调用2.1 open2.1.1 参数2:flags2.1.2 参数3:mode2.1.3 返回值——file descriptor 2.2 write2.3 read2.4 close 3 文件的本质3.1 struct file3.2 一个进程如何与多个文件相关…

倒计时模块复习

经典回顾倒计时 倒计时的基本布局介绍。 一个内容区域和一个输入区域,内容区域进行划分 直接使用flex布局会更快一点。 js代码 我们利用一下模块化思想,直接把获得时间这个功能写成一个函数。方便后续的调用 function getTime() {const date new Date…

使用pytorch查看中间层特征矩阵以及卷积核参数

这篇是我对哔哩哔哩up主 霹雳吧啦Wz 的视频的文字版学习笔记 感谢他对知识的分享 1和4是之前讲过的alexnet和resnet模型 2是分析中间层特征矩阵的脚本 3是查看卷积核参数的脚本 1设置预处理方法 和图像训练的时候用的预处理方法保持一致 2实例化模型 3载入之前的模型参数 4载入…

智能优化算法应用:基于驾驶训练算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于驾驶训练算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于驾驶训练算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.驾驶训练算法4.实验参数设定5.算法结果6.参考…

带大家做一个,易上手的家常辣子鸡

先从冰箱拿出鸡肉解冻 拿小半根葱 去掉最外面一层皮 切成小段 最备好 花椒 干辣椒 准备四五个大料 起锅烧油 这道菜需要放其他菜两到三倍的油 油温上来之后 放入干辣椒和花椒进行翻炒 等它们都烧黑之后捞出来 这样 辣味就留在油里面了 然后 倒入鸡肉 葱段 大料 然后 倒…

从0到1,手把手带你开发截图工具ScreenCap------001实现基本的截图功能

ScreenCap---Version:001 说明 从0到1,手把手带你开发windows端的截屏软件ScreenCap 当前版本:ScreenCap---001 支持全屏截图 支持鼠标拖动截图区域 支持拖拽截图 支持保存全屏截图 支持另存截图到其他位置 GitHub 仓库master下的Scr…

如何排查rpc mount export: RPC: Timed out问题

文章目录 问题描述查看nfs服务是否运行正常如果以上都通过,尝试下面步骤 问题描述 我们将讨论您在 NFS 客户端上看到的 NFS 错误之一的故障排除。在尝试与 NFS 相关的命令时可以看到此错误,如下所示: 通常,当您看到此错误时,您也…

整合消息队列RabbitMQ

为什么使用消息队列MQ? 因为使用消息队列有多个好处:可以实现系统服务的解耦、异步和削峰: 异步通信:消息队列提供了一种异步通信的方式,发送方可以将消息发送到队列中,然后继续执行其他任务,…

vue使用甘特图dhtmlxgantt + gantt.addTaskLayer

效果图: 甘特图 官网地址 gantt安装与使用 vue版---部分功能收费 安装gantt 或 引入文件 npm install dhtmlx-gantt -save或import gantt from "/public/static/dhtmlxgantt/dhtmlxgantt.js"; import "/public/static/dhtmlxgantt/locale/local…

Pytest+Yaml+Excel 接口自动化测试框架的实现示例

一、框架架构 二、项目目录结构 三、框架功能说明 解决痛点: 通过session会话方式,解决了登录之后cookie关联处理框架天然支持接口动态传参、关联灵活处理支持Excel、Yaml文件格式编写接口用例,通过简单配置框架自动读取并执行执行环境一键…

python3.5安装教程及环境配置,python3.7.2安装与配置

大家好,小编来为大家解答以下问题,python3.5安装教程及环境配置,python3.7.2安装与配置,现在让我们一起来看看吧! python 从爬虫开始(一) Python 简介 首先简介一下Python和爬虫的关系与概念&am…

深度学习实战65-人脸检测模型LFFD的搭建,LFFD模型的架构与原理的详细介绍

大家好,我是微学AI,今天给大家介绍一下深度学习实战65-人脸检测模型LFFD的搭建,LFFD模型的架构与原理的详细介绍。LFFD(Light and Fast Face Detector)模型是一种用于人脸检测的深度学习模型,其设计旨在实现轻量级和快速的人脸检测。本文将详细介绍LFFD模型的定义、优点、原…

类人智能体概念、能力与衍生丨AI Agents闭门研讨观点集锦

导读 在智源社区举办的「青源Workshop第27期:AI Agents 闭门研讨会」上,来自英伟达的高级应用科学家王智琳、CAMEL一作李国豪、AutoAgents一作陈光耀,以及相关技术专家们共同参与交流讨论,分享了最新的研究成果,共同探…