从库函数到API接口,深挖不同语言背后的“封装”与“调用”思想
个人主页-爱因斯晨
优秀文章推荐
文章目录
- 个人主页-爱因斯晨
- 优秀文章推荐
- 引言
- 一、三种调用机制概述
- C语言的库函数
- Python 的导包机制
- Java 的 API 接口调用
- 综上:
- 二、它们的相同点:封装与调用
- 三、不同之处
- **对比核心维度**
- **细节串讲**
- 1. **C 语言:最原始的“过程式调用”**
- 2. **Python:模块化 + 面向对象**
- 3. **Java:纯面向对象 + 严格接口**
- 通俗理解:不同“买菜方式”
- 四、统一视角下的“调用模型”
- 五、总结升华
引言
作为一个小菜鸟,在恶补C语言库函数
的时候,联想到这与Java
中的API接口
和Python
中的导入模块
是不是本质上就是调用封装好的代码,在本语言中的能效是不是一样的。我感觉应该是大差不差,但是做学问不能大差不差。于是,我悄悄的去查了一下,我猜对了哈哈。本质上是一样的,思想上是一样的,但在底层原理和调用机制上有些差别,也就是有了语言特色。我能有这样的想法,值得小小的骄傲一下。抽象思考的开始就是在进步~
针对这一问题正文开始:
一、三种调用机制概述
我们先来看看这三种语言在代码中的基本使用方式:
C语言的库函数
C 是一种过程式语言,没有类和对象的概念。我们使用 #include
指令引入标准库头文件,然后调用其中的函数。例如:
#include <stdio.h>int main() {printf("Hello, world!\n");return 0;
}
printf()
就是标准库 stdio.h
中封装好的一个函数。使用者无需关心其内部实现,只需知道用法即可。
Python 的导包机制
Python 提倡模块化开发,标准库和第三方库都以“模块”的形式存在,使用时通过 import
语句引入。例如:
import math
print(math.sqrt(25))
你也可以选择性导入模块中的某个函数:
from math import sqrt
print(sqrt(25))
模块中可以包含函数、类、变量等内容。Python 的导入机制十分灵活,符合其动态解释型语言的特性。
像这样的常用的还有:
import numpy as np #数值计算
import pandas as pd #数据分析处理
import matplotlib.pyplot as plt #数据可视化
不要问博主为什么熟悉这三个模块,问就是数模的痛啊!!
Java 的 API 接口调用
Java 是面向对象语言,一切都以“类”的方式封装。我们通过 import
语句引入需要使用的类,再通过对象或静态方式调用其方
法。例如:
import java.util.ArrayList;public class Demo {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("Hello");System.out.println(list.get(0));}
}
Java 的类库庞大、分类严谨,并且有详细的文档支持(Java API 文档),是开发中不可或缺的一部分。博主至今没找到和阿伟
老师同一版的API文档,有的小伙伴儿请分享给博主啊,主页介绍有微信,求求了。博主的主要学习语言是java,Py
和C
学的
不深呐
综上:
C语言库函数是通过 #include
引入头文件 + 链接库文件。
Python 中通过 import
语句导入模块或包。
Java 中通过 import
引入类/接口,通过 API 使用类库功能。
二、它们的相同点:封装与调用
我们看了他们的调用方式,现在来盘点一下就是是怎样一个相同的本质:
无论是哪种语言,这些机制都有一个共同目标:
封装好的功能模块可直接调用,提升开发效率。
总结起来,它们都具备以下特征:
- 都是封装调用机制
- 隐藏内部实现,暴露接口/函数/类
- 目的是复用代码、提高效率
- 可组合使用,形成更大程序
注:有朋友可能会误解:**封装不是在java中才有的吗?**在java中,封装确实作为面向对象编程三大块之一(封装、继承、多态)。
但不是它特有的,它是所有现代编程语言中普遍存在的一种软件设计思想,只是 Java 对封装的表达最为“显式”和“制度化”,所
以很多人第一次认真接触封装,往往是在 Java 中。
三、不同之处
对比核心维度
比较维度 | C 语言(库函数) | Python(导包) | Java(API 接口) |
---|---|---|---|
使用方式 | #include <stdio.h> | import math | import java.util.List |
调用方式 | printf() | math.sqrt() | list.get(0) |
类型 | 函数库(头文件+链接库) | 模块、包、类 | 类库、接口、类 |
底层机制 | 静态/动态链接 | 动态解释器导入(模块缓存) | JVM 加载 .class 文件 |
面向对象 | 否(过程式) | 是(支持 OOP) | 是(纯 OOP) |
封装灵活性 | 低(靠程序员自觉) | 高(可灵活封装) | 中(封装严格) |
细节串讲
1. C 语言:最原始的“过程式调用”
- 用
#include
把头文件里写好的声明引入进来(告诉编译器有这些函数)。 - 真正的实现在
.c
文件里,通过编译器生成的目标文件或链接库.lib
/.so
/.dll
被链接进程序。 static
可以让函数只在文件内可见,相当于局部封装。- C 只提供了最小的封装手段,程序员需要靠命名和约定去遵守接口和封装(没有访问控制符)。
优点:非常灵活,高效。
缺点:没有强制封装和可扩展的模块系统,容易踩坑。
2. Python:模块化 + 面向对象
- 用
import
把整个模块或其中部分成员引入到当前命名空间。 - 模块可以包含变量、函数、类等,是功能单元。
- 通过
_
和__all__
机制来控制哪些是“对外接口”,哪些是“内部实现”。 - Python 解释器在运行时动态加载模块,会缓存到
sys.modules
中,效率高、灵活性强。
优点:组织方式灵活,既可以面向过程(只用函数),也可以面向对象(类、方法)。
缺点:访问控制靠约定(下划线命名),不是强制性的。
3. Java:纯面向对象 + 严格接口
- 一切功能都在类中封装,通过对象和方法调用。
import
是告诉编译器/IDE你要用哪个包里的类,JVM 在运行时加载.class
文件。- 有明确的访问修饰符:
public
、private
、protected
,配合interface
和abstract
保证了模块之间只能通过“黑盒”方式调用。 - 强调文档化(JavaDoc),接口设计尽可能稳定,方便多人协作和大型项目维护。
优点:封装严格,依赖清晰,便于大型工程合作。
缺点:灵活性相对较低,不允许你随便“越界”访问实现细节。
举个例子:你要计算平方根
- C语言:使用
sqrt()
,要链接 math 库 - Python:
import math
后直接用math.sqrt()
- Java:用
Math.sqrt()
,它是标准类库中静态方法的一部分
注:读到这里你有没有联想到函数?函数与这三者的本质一样吗?
答案是:是的,本质一样,都是封装好的功能单元的调用。
- 自己写的函数:是你自己封装的功能逻辑
- 库函数/API:是别人写好的封装逻辑,你通过调用接口使用
它们的区别只是:
维度 | 自己写的函数 | 库函数 / 模块 / API |
---|---|---|
实现者 | 你自己 | 第三方/语言标准库 |
可控性 | 高(可改) | 低(只调用) |
抽象层次 | 局部封装 | 系统/模块级封装 |
可以说,从函数 → 模块 → API,是功能封装粒度越来越大的过程。
通俗理解:不同“买菜方式”
可以用一个比喻来形象地理解它们:
- C语言像超市自己搬货:你去超市买东西,得知道哪个货架在哪,手动挑选并结账(头文件 + 链接库)。
- Python像点外卖:你说“我要牛奶”,平台自动给你送来,不用关心它从哪来的(解释器动态导入模块)。
- Java像公司采购:你申请一份需求,走审批流程,用标准接口对接供应商(类与接口,编译与JVM约束更严格)。
四、统一视角下的“调用模型”
JAVA、C、Python 是这样。那么我们格局打开:抽象所有调用方式,可以看到一个共同模型:
[调用者] ——(通过接口)——> [被调用者的封装逻辑]
这个模型不依赖语言,不依赖调用方式。只要满足:
- 有清晰的调用入口(接口、函数、方法)
- 有明确的封装边界(实现不可见)
- 有调用和被调用的分离(你调用的是“黑盒”)
那它就是一种“统一的调用机制”。是不是豁然开朗捏~
五、总结升华
可能我的这篇博客在资深程序员看来,像极了在论证一个已知的常识。就像我写了2k字在论证人活着要呼吸一样。其实我的这个思考对于我自身来说是有很大意义的,也可以算个进步的开始,开始有想法了。学编程不只是会用语言,而是在理解语言的“灵魂”——这才是编程真正的魅力所在。最后用一句话作为结尾,送给我,也送给不断攀登的年轻人:
青年人的血液应该是液态阳光!