面向对象编程 (OOP):深入理解继承、多态和抽象

1. 简介

        面向对象编程 (OOP) 是一种强大的编程范式,它通过将程序组织成对象的集合来简化软件设计和开发。与传统的程序设计方法相比,OOP 提供了一种更自然、更易于理解和维护的方式来构建复杂的软件系统。OOP 的核心概念包括:对象、类、继承、多态、封装。本文将深入探讨这些概念,重点讲解继承、多态、抽象类和接口,以及它们在 Java 中的应用。

2. 栈空间和堆空间

        在深入了解 OOP 之前,我们需要先了解 Java 中的内存管理机制,尤其是栈空间和堆空间。

2.1 栈空间 (Stack)

  • 定义和作用: 栈空间用于存储局部变量、方法参数和函数调用信息。 它是 Java 程序运行时最基本的内存区域之一。
  • LIFO 原理: 栈空间遵循先进后出 (LIFO) 的原则,就像一个叠放盘子的架子,最后放进去的盘子最先被拿出来。
  • 存储数据类型: 栈空间主要存储以下数据类型:
    • 局部变量: 定义在方法内部的变量,例如 int age = 25;
    • 方法参数: 传递给方法的变量,例如 void calculateSum(int a, int b) { ... } 中的 a 和 b
    • 函数调用信息: 包括方法调用时的局部变量地址、返回地址等。
  • 特点:
    • 栈空间大小通常较小,而且速度较快。
    • 栈空间的分配和回收由 Java 虚拟机 (JVM) 自动管理,程序员不需要手动进行操作。

2.2 堆空间 (Heap)

  • 定义和作用: 堆空间用于存储对象和数组。它是 Java 程序中用于动态内存分配的主要区域。
  • 特点:
    • 堆空间的空间大小通常比栈空间大得多。
    • 堆空间的分配和回收由垃圾回收器 (Garbage Collector) 自动管理,程序员一般不需要手动进行操作。
    • 堆空间通常比栈空间速度慢。

2.3 栈空间和堆空间的交互

当创建一个对象时,会发生以下步骤:

  1. 栈空间: 分配一个引用变量,该变量指向堆空间中对象的地址。例如:Car myCar = new Car(); 中的 myCar
  2. 堆空间: 为新创建的对象分配一块内存块,其中包含对象的属性和方法。
  3. 连接: 引用变量指向堆空间中分配的内存块,这样就可以通过引用变量访问对象。
// 1. 栈空间:
// 创建一个 Car 类对象,并分配了一个引用变量 myCar。
Car myCar = new Car(); // 2. 堆空间:
// 将新创建的 Car 对象的属性和方法存储在堆空间中。
// 这里假设 Car 有两个属性:color 和 model。
// myCar 的值指向堆空间中对象的地址。
// 此时 myCar 就是一个指向堆空间对象的引用。
//         堆空间
// +-----+-----+---------+     // 
// | color| model|  ...   |     //
// +-----+-----+---------+
//       ^
//       |
//       myCar(栈空间)

3. 面向对象编程的基础

3.1 对象和类

  • 对象: 现实世界中事物的抽象表示。在编程中,对象是数据(属性)和操作数据的方法(行为)的封装。例如,一个 "汽车" 对象可以包含属性(例如颜色、品牌、型号、速度)和方法(例如启动、加速、刹车)。
  • 类: 创建对象的模板或蓝图。它定义了对象的属性和方法。例如,"汽车" 类可以定义所有汽车共有的属性和方法,然后通过这个类创建多个不同的汽车对象。

用 Java 代码表示:

class Car {String color;String brand;String model;int speed;void start() {System.out.println("汽车启动");}void accelerate() {System.out.println("汽车加速");}void brake() {System.out.println("汽车刹车");}
}public class Main {public static void main(String[] args) {Car myCar = new Car();myCar.color = "红色";myCar.brand = "宝马";myCar.model = "3系";myCar.start();myCar.accelerate();}
}

3.2 封装

  • 概念: 将对象的属性和方法结合起来,并隐藏对象的内部实现细节,只暴露接口供外部访问。
  • 目的:
    • 提高代码安全性: 防止外部代码直接修改对象的私有属性。
    • 提升代码可维护性: 修改对象的内部实现细节不会影响外部代码的使用。
    • 增强代码可重用性: 可以根据需要创建不同的对象,而无需关注其内部实现细节。

访问修饰符:

修饰符描述访问范围
public任何地方都可以访问整个程序
private只有类内部可以访问类内部
protected继承的类和同一个包内的类可以访问继承类和同一个包
default (无修饰符)只有同一个包内的类可以访问同一个包

用 Java 代码示例:

class Person {private String name; // 私有属性,只能在 Person 类内部访问private int age; // 私有属性,只能在 Person 类内部访问public String getName() { // 公共方法,可以在任何地方访问return name;}public void setName(String name) { // 公共方法,可以在任何地方访问this.name = name;}public int getAge() { // 公共方法,可以在任何地方访问return age; }public void setAge(int age) { // 公共方法,可以在任何地方访问this.age = age;}
}

4. 继承

  • 概念: 继承是 OOP 中一个重要的特性,它允许一个类继承另一个类的属性和方法。继承建立了 “is-a” 关系,子类拥有父类的所有属性和方法,并且可以添加自己的属性和方法。
  • 目的:
    • 代码复用: 避免重复编写相同的功能代码。
    • 可扩展性: 通过继承,可以在父类的基础上创建新的子类,实现新的功能。
    • 代码组织: 将相关的功能组织到不同的层次结构中,使代码更易于理解和维护。

4.1 继承的概念

  • 父类 (基类或超类): 被继承的类。
  • 子类 (派生类或扩展类): 继承自另一个类的类。
class Animal {void eat() {System.out.println("动物在吃");}
}class Dog extends Animal { // Dog 继承了 Animal 类void bark() {System.out.println("狗在叫");}
}

4.2 继承的优势

  • 代码复用: 继承允许子类复用父类的代码,避免重复编写相同的功能。例如,在 Dog 类中,eat 方法不需要重新编写,可以直接继承自父类 Animal
  • 可扩展性: 继承使得添加新的功能变得更容易。例如,我们可以通过继承 Animal 类,创建新的子类,比如 Cat 类,来添加猫的相关功能,例如 meow() 方法。
  • 代码组织: 继承可以帮助我们更好地组织代码,将相关的类组织到不同的层次结构中。例如,我们可以创建一个 Pet 类作为父类,然后创建 DogCat 等子类,这样可以使代码更加清晰、易于维护。

4.3 继承的类型

  • 单继承: 在 Java 中,一个子类只能继承一个父类。
  • 多继承: 一个子类可以继承多个父类。 Java 不支持真正的多继承,但可以使用接口来实现类似功能。
  • 层次化继承: 父类可以有子类,子类可以有孙类,形成层次结构。

4.4 继承中的方法重写 (Overriding)

  • 概念: 子类可以选择重写父类的方法,以便在子类中提供不同的实现。
  • 条件: 方法重写必须满足以下条件:
    • 方法名相同。
    • 参数列表相同。
    • 返回值类型相同(或者返回值类型是父类返回值类型的子类)。
    • 访问修饰符的权限不能比父类更严格。
class Animal {void sound() {System.out.println("动物发出声音");}
}class Dog extends Animal {@Overridevoid sound() {  // 重写父类的 sound 方法System.out.println("狗叫");}
}

4.5 继承中的构造函数

  • 子类构造函数: 子类构造函数必须调用父类构造函数,才能初始化父类继承的属性。
  • super() 方法: 在子类构造函数中,可以使用 super() 方法调用父类的构造函数。

4.6 继承中的方法隐藏

  • 概念: 子类的方法与父类的某个方法具有相同的方法名,但参数列表不同,这种情况称为方法隐藏。
  • 区别: 方法隐藏与方法重写不同,方法隐藏不会改变方法的实现,而方法重写会改变方法的实现。
class Animal {void sound() { // 父类方法System.out.println("Animal makes a sound");}
}class Dog extends Animal {void sound(int age) { // 子类方法,与父类方法同名,但参数不同System.out.println("Dog barks, age: " + age);}
}

4.7 继承中 final 关键字

  • final 关键字: 用于修饰类、方法和变量,表示它们是最终的,不能被继承或重写。
    • final 类: 表示该类不能被继承。
    • final 方法: 表示该方法不能被子类重写。
    • final 变量: 表示该变量是一个常量,其值一旦被赋值就不能再改变。

5. 多态

  • 概念: 多态是指同一个操作在不同的对象上会产生不同的行为。
  • 目的:
    • 代码灵活性和可扩展性: 可以通过父类引用指向子类对象,调用不同的实现方法。
    • 提高代码可读性: 可以使用更简洁、更灵活的方式来编写代码。

5.1 多态的概念

  • 父类引用: 可以使用父类类型的变量来引用子类对象。
  • 方法调用: 当调用父类引用中的方法时,实际执行的是子类重写后的方法。
class Animal { void sound() {System.out.println("动物发出声音");}
}class Dog extends Animal {@Overridevoid sound() {System.out.println("狗叫");}
}public class Main {public static void main(String[] args) {Animal myDog = new Dog(); // 父类引用指向子类对象myDog.sound(); // 调用的是 Dog 类的 sound 方法}
}

5.2 多态的类型

  • 方法重载 (Overloading): 同一个类中,方法名相同,参数列表不同。 编译器会根据参数类型和数量选择合适的重载方法。
  • 方法重写 (Overriding): 子类重写父类的方法。 当父类引用指向子类对象时,调用的是子类重写后的方法。

5.3 多态的优势

  • 代码灵活性和可扩展性: 多态可以使代码更加灵活和易于扩展。
  • 代码可读性: 多态可以使代码更加简洁和易于理解。

5.4 多态的应用场景

        多态在实际开发中有很多应用场景,例如:

  • 工厂模式: 通过工厂类创建不同类型的对象。
  • 策略模式: 定义一组算法,并将它们封装为独立的类,以便在运行时选择合适的算法。

5.5 抽象类

  • 概念: 抽象类是用 abstract 关键字修饰的类,它不能被直接实例化,只能被子类继承。抽象类可以包含抽象方法和普通方法。
  • 特点:
    • 抽象方法: 没有方法体,以 abstract 关键字修饰。 子类必须重写抽象方法才能实例化。
    • 不能被直接实例化: 只能通过子类来实例化。
abstract class Shape { // 抽象类abstract void draw(); // 抽象方法,没有方法体void print() { // 普通方法System.out.println("这是一个形状");}
}class Circle extends Shape {@Overridevoid draw() {System.out.println("画一个圆形");}
}public class Main {public static void main(String[] args) {Shape circle = new Circle(); // 实例化子类 Circlecircle.draw(); // 调用子类重写的 draw 方法circle.print(); // 调用父类的 print 方法}
}

5.6 接口

  • 概念: 接口是使用 interface 关键字声明的,它是一种特殊的抽象类,其中只包含抽象方法和常量。接口不能被直接实例化,只能被类实现。
  • 特点:
    • 只能包含抽象方法和常量。
    • 可以被多个类实现。
    • 提高代码的可扩展性和灵活性。
interface Drawable { // 接口void draw(); // 抽象方法
}class Circle implements Drawable { // 实现接口@Overridepublic void draw() {System.out.println("画一个圆形"); }
}public class Main {public static void main(String[] args) {Drawable circle = new Circle(); // 实例化 Circle 对象circle.draw();}
}

6. 总结

概念描述优势
对象现实世界中事物的抽象表示,包含属性和方法提供了一种更自然、更易于理解和维护的编程方式
创建对象的模板,定义对象的属性和方法定义了对象的结构和行为
封装将对象的属性和方法结合起来,隐藏实现细节提高代码安全性、可维护性和可重用性
继承允许子类继承父类的属性和方法代码复用、可扩展性、代码组织
多态同一个操作在不同的对象上会产生不同的行为代码灵活性和可扩展性、提高代码可读性
抽象类用 abstract 修饰的类,不能被直接实例化,只能被子类继承定义公共方法和属性,并强制子类实现抽象方法
接口用 interface 关键字定义,包含抽象方法和常量,可以被多个类实现提高代码的可扩展性和灵活性

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

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

相关文章

Java进阶学习笔记31——日期时间

Date: 代表的是日期和时间。 分配Date对象并初始化它以表示自标准基准时间(称为纪元)以来的指定毫秒数,即1970年1月1日00:00:00。 有参构造器。 package cn.ensource.d3_time;import java.util.Date;public class Test1Date {pu…

Java—异常处理

异常的结构图 异常知识点 异常分类: 按照在程序编译阶段是否被检查,异常分为编译时异常(Checked Exception)和运行时异常(Unchecked Exception)。编译时异常是指必须进行显式处理的异常,例如IOE…

【Linux】写一个日志类

文章目录 1. 源代码2. 函数功能概览3. 代码详细解释3.1 头文件和宏定义3.2 Log类定义3.3 打印日志的方法3.4 操作符重载和析构函数3.5 可变参数函数的原理 4. 测试用例 1. 源代码 下面代码定义了一个 Log 类,用于记录日志信息。这个类支持将日志信息输出到屏幕、单…

Java扩展机制:SPI与Spring.factories详解

一、SPI SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。 整体机制图如下: Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。 系统设计的各个抽象,往往有很多不…

戴尔科技:一盆冷水浇醒了AIPC

这年头,只要沾上英伟达的公司,不论美股还是大A,都跟着鸡犬升天几轮过,但昨晚英伟达蒸发1064亿美元, 跟着遭罪的也不少,有没有一夜惊魂梦醒的感觉? 今天我们来说说——戴尔科技。 昨晚戴尔科技大跌5.18%&a…

5G无线标准演进综述及新技术引入

摘 要 随着经济和社会的发展,5G业务越来越丰富多彩,1080P高清视频、裸眼3D、网联汽车、云手机等新业务、新终端对网络的要求也越来越高;另一方面,5G标准持续演进,在MIMO、载波聚合、移动性管理、uRLLC、切片、定位等方…

模仿库实现priority_queue

1 priority_queue 1.1 概念 优先级队列,一种大/小堆(默认为大堆) 1.2 大堆和小堆 一种完全二叉树,大堆根节点一定比子字节大 小堆根节点一定比子字节小 向下调整 从根节点开始比较与子节点的大小不断向下 向上调整 找到最后一个非叶子节点&#xf…

mac多媒体影音库:Emby for Mac 中文版

Emby软件是一款功能强大的媒体服务器软件,旨在为用户提供丰富的多媒体体验。以下是关于Emby软件的详细介绍: 下载地址:https://www.macz.com/mac/7964.html?idOTI2NjQ5Jl8mMjcuMTg2LjE1LjE4Mg%3D%3D 主要功能 媒体管理:Emby允许用…

代码随想录-Day25

216.组合总和III 找出所有相加之和为 n 的 k 个数的组合,且满足下列条件: 只使用数字1到9 每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。 示例 1: 输入: k 3, n 7 输…

Python OCR 图片转文字进阶:读光OCR之行检测模型+行识别模型

Python OCR 图片转文字进阶:读光OCR之行检测模型行识别模型 介绍阿里云文字识别OCR(读光OCR)前置条件模型1:行检测模型模型1:行识别模型 代码:main.py 介绍 什么是OCR? OCR是“Optical Charac…

德人合科技——@天锐绿盾 | -文档透明加密系统

天锐绿盾文档透明加密系统是一种先进的数据安全解决方案,旨在保护企业和组织的敏感信息,防止未经授权的访问和泄漏。 PC地址: https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 以下是该系统的一些关键特点和功…

[C++11/14新特性] tuple元组介绍

C11 标准新引入了一种类模板,命名为 tuple(中文可直译为元组)。tuple 最大的特点是:实例化的对象可以存储任意数量、任意类型的数据。tuple 的应用场景很广泛,例如当需要存储多个不同类型的元素时,可以使用…

3D目标检测入门:探索OpenPCDet框架

前言 在自动驾驶和机器人视觉这两个飞速发展的领域中,3D目标检测技术扮演着核心角色。随着深度学习技术的突破性进展,3D目标检测算法的研究和应用正日益深入。OpenPCDet,这个由香港中文大学OpenMMLab实验室精心打造的开源工具箱,…

【用Python画画】六一儿童节画爱心

本文收录于 《Python编程入门》专栏,从零基础开始,分享一些Python编程基础知识,欢迎关注,谢谢! 文章目录 一、前言二、代码示例三、知识点梳理四、总结 一、前言 本文介绍如何使用Python的海龟画图工具turtle&#xf…

堆排序的实现

在上一篇博客中,介绍了堆的实现,现在来介绍一下堆排序。 一.打印有序: 现在先给一个无序的数组,现在我们利用我们实现的堆的功能先完成一下打印排序: 在for循环里是一个建堆的过程,每来一个数据就放入堆中…

linux进程的加载和启动过程分析

我们的源代码通过预处理,编译,汇编,链接后形成可执行文件,那么当我们在终端敲下指令$ ./a.out argv1 argv2 后,操作系统是怎么将我们的可执行文件加载并运行的呢? 首先知道,计算机的操作系统的启动程序是写死在硬件上的,每次计算机上电时,都将自动加载启动程序,之后…

python第五次作业

1.请实现一个装饰器,每次调用函数时,将函数名字以及调用此函数的时间点写入文件中 # 导入datetime模块,用于获取当前时间并格式化输出 import datetime# 定义一个装饰器工厂函数log_funcName_time,它接受一个参数time def log_fu…

红外听力教学考试系统-红外语音听力广播在大学英语四六级听力考试中应用

红外听力教学考试系统-红外语音听力广播在大学英语四六级听力考试中的应用 由北京海特伟业科技有限公司任洪卓发布于2024年6月1日 红外语音听力广播(即红外听力教学考试系统)在英语四六级听力考试的应用正日益凸显出其重要性和优越性。在当前的高等教育…

xcode删除依赖包package,删除不必要的依赖项

点击项目,然后点击PROJECT项里面的Package DepenDependencies: 选中一个依赖项,然后点击减号,就可以把依赖项删除掉了,左侧项目下面的Package已经没有了这个依赖项 TARGET下面的package也要删除:在这里删除…

大数据分析统计

大数据分析统计 from datetime import datetimeimport pandas as pd import matplotlib.pyplot as pltpm25files [PM2.5_2021.csv, PM2.5_2022.csv, PM2.5_2023.csv] pm10files [PM10_2021.csv, PM10_2022.csv, PM10_2023.csv]def read_csv_file(files):# 每个文件都有表头…