面向对象编程 (OOP):深入理解继承、多态和抽象
创作时间:
作者:
@小白创作中心
面向对象编程 (OOP):深入理解继承、多态和抽象
引用
CSDN
1.
https://blog.csdn.net/weidl001/article/details/139340463
面向对象编程(OOP)是一种强大的编程范式,它通过将程序组织成对象的集合来简化软件设计和开发。本文将深入探讨OOP的核心概念,重点讲解继承、多态、抽象类和接口,以及它们在Java中的应用。
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 栈空间和堆空间的交互
当创建一个对象时,会发生以下步骤:
- 栈空间: 分配一个引用变量,该变量指向堆空间中对象的地址。例如:
中的Car myCar = new Car();
myCar
。 - 堆空间: 为新创建的对象分配一块内存块,其中包含对象的属性和方法。
- 连接: 引用变量指向堆空间中分配的内存块,这样就可以通过引用变量访问对象。
// 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
类作为父类,然后创建Dog
、Cat
等子类,这样可以使代码更加清晰、易于维护。
4.3 继承的类型
- 单继承: 在Java中,一个子类只能继承一个父类。
- 多继承: 一个子类可以继承多个父类。Java不支持真正的多继承,但可以使用接口来实现类似功能。
- 层次化继承: 父类可以有子类,子类可以有孙类,形成层次结构。
4.4 继承中的方法重写(Overriding)
- 概念: 子类可以选择重写父类的方法,以便在子类中提供不同的实现。
- 条件:
- 方法名相同。
- 参数列表相同。
- 返回值类型相同(或者返回值类型是父类返回值类型的子类)。
- 访问修饰符的权限不能比父类更严格。
class Animal {
void sound() {
System.out.println("动物发出声音");
}
}
class Dog extends Animal {
@Override
void 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 {
@Override
void 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 {
@Override
void draw() {
System.out.println("画一个圆形");
}
}
public class Main {
public static void main(String[] args) {
Shape circle = new Circle(); // 实例化子类 Circle
circle.draw(); // 调用子类重写的 draw 方法
circle.print(); // 调用父类的 print 方法
}
}
5.6 接口
- 概念: 接口是使用
interface
关键字声明的,它是一种特殊的抽象类,其中只包含抽象方法和常量。接口不能被直接实例化,只能被类实现。 - 特点:
- 只能包含抽象方法和常量。
- 可以被多个类实现。
- 提高代码的可扩展性和灵活性。
interface Drawable { // 接口
void draw(); // 抽象方法
}
class Circle implements Drawable { // 实现接口
@Override
public void draw() {
System.out.println("画一个圆形");
}
}
public class Main {
public static void main(String[] args) {
Drawable circle = new Circle(); // 实例化 Circle 对象
circle.draw();
}
}
6. 总结
概念 | 描述 | 优势 |
---|---|---|
对象 | 现实世界中事物的抽象表示,包含属性和方法 | 提供了一种更自然、更易于理解和维护的编程方式 |
类 | 创建对象的模板,定义对象的属性和方法 | 定义了对象的结构和行为 |
封装 | 将对象的属性和方法结合起来,隐藏实现细节 | 提高代码安全性、可维护性和可重用性 |
继承 | 允许子类继承父类的属性和方法 | 代码复用、可扩展性、代码组织 |
多态 | 同一个操作在不同的对象上会产生不同的行为 | 代码灵活性和可扩展性、提高代码可读性 |
抽象类 | 用 abstract 修饰的类,不能被直接实例化,只能被子类继承 | 定义公共方法和属性,并强制子类实现抽象方法 |
接口 | 用 interface 关键字定义,包含抽象方法和常量,可以被多个类实现 | 提高代码的可扩展性和灵活性 |
热门推荐
藤茶的食用价值及其健康效益
手机停机后能否接收短信?
迅雷占用内存多?
STM32存储器和总线架构深度解析:从内核到外设的全链路设计
越野卡丁车需要驾照吗?
卡丁车与平衡车租赁合同:法律规范与责任划分
金庸《笑傲江湖》的历史背景考:万历年间的大明江湖
大学新生活不适应?送你舒心指南!
高性能轿车动力系统优化指南及福克斯三厢高速油耗解析
全面解析VAT业务注册:让你的国际化事业更上层楼
家长过度溺爱,将成为孩子的成长枷锁?
电子灌封胶的使用指南:步骤解析及使用注意事项
追逐梦想的脚步:足球明星的奋斗与辉煌之路
深入浅出正念冥想:带你领略内心平和的秘诀
孩子屏幕使用时间引发关注,家长需重视户外运动与营养
面试8问,看完就拿下offer!
DDS协议详解:物联网时代的数据分发服务
DDS:保障物联网系统的稳定运行和高效协作
证监会持续放大招!大跌、连跌“要负责”,受影响公司名单来了!
电脑风扇安装全攻略:轻松上手教程
微波射频电路板微带线与带状线布局技巧
笔记本处理器选择指南:挑选最适合你的笔记本处理器
为什么财富管理?怎样进行有效的财富管理?
96岁陈灏珠院士:最佳的防冠心病方法不是打太极,很多人在做
临汾的十大硬菜
触发价格的设置方法及其应用场景
美国临床肿瘤学会指南:癌症患者治疗期间如何正确运动?
公务员职级晋升与年度考核:职级晋升与薪酬增长趋势分析,两年进档工资涨幅揭秘
孕期歧视:如何与公司谈判,保护自身权益
饼干制作全攻略:植物油代替黄油、电饭锅烤箱双选、发酵粉应用详解