从库函数到API接口,深挖不同语言背后的“封装”与“调用”思想

个人主页-爱因斯晨

优秀文章推荐

文章目录

引言

作为一个小菜鸟,在恶补C语言库函数的时候,联想到这与Java中的API接口Python中的导入模块是不是本质上就是调用封装好的代码,在本语言中的能效是不是一样的。我感觉应该是大差不差,但是做学问不能大差不差。于是,我悄悄的去查了一下,我猜对了哈哈。本质上是一样的,思想上是一样的,但在底层原理和调用机制上有些差别,也就是有了语言特色。我能有这样的想法,值得小小的骄傲一下。抽象思考的开始就是在进步~

针对这一问题正文开始:

一、三种调用机制概述

我们先来看看这三种语言在代码中的基本使用方式:

C语言的库函数

C 是一种过程式语言,没有类和对象的概念。我们使用 #include 指令引入标准库头文件,然后调用其中的函数。例如:

c 复制代码
#include <stdio.h>

int main() {
    printf("Hello, world!\n");
    return 0;
}

printf() 就是标准库 stdio.h 中封装好的一个函数。使用者无需关心其内部实现,只需知道用法即可。


Python 的导包机制

Python 提倡模块化开发,标准库和第三方库都以"模块"的形式存在,使用时通过 import 语句引入。例如:

python 复制代码
import math
print(math.sqrt(25))

你也可以选择性导入模块中的某个函数:

python 复制代码
from math import sqrt
print(sqrt(25))

模块中可以包含函数、类、变量等内容。Python 的导入机制十分灵活,符合其动态解释型语言的特性。

像这样的常用的还有:

python 复制代码
import numpy as np #数值计算
python 复制代码
import pandas as pd #数据分析处理
python 复制代码
import matplotlib.pyplot as plt #数据可视化

不要问博主为什么熟悉这三个模块,问就是数模的痛啊!!


Java 的 API 接口调用

Java 是面向对象语言,一切都以"类"的方式封装。我们通过 import 语句引入需要使用的类,再通过对象或静态方式调用其方

法。例如:

java 复制代码
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,PyC学的

不深呐

综上:

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 文件。
  • 有明确的访问修饰符:publicprivateprotected,配合 interfaceabstract 保证了模块之间只能通过"黑盒"方式调用。
  • 强调文档化(JavaDoc),接口设计尽可能稳定,方便多人协作和大型项目维护。

优点:封装严格,依赖清晰,便于大型工程合作。

缺点:灵活性相对较低,不允许你随便"越界"访问实现细节。

举个例子:你要计算平方根

  • C语言:使用 sqrt(),要链接 math 库
  • Python:import math 后直接用 math.sqrt()
  • Java:用 Math.sqrt(),它是标准类库中静态方法的一部分

注:读到这里你有没有联想到函数?函数与这三者的本质一样吗?

答案是:是的,本质一样,都是封装好的功能单元的调用

  • 自己写的函数:是你自己封装的功能逻辑
  • 库函数/API:是别人写好的封装逻辑,你通过调用接口使用

它们的区别只是:

维度 自己写的函数 库函数 / 模块 / API
实现者 你自己 第三方/语言标准库
可控性 高(可改) 低(只调用)
抽象层次 局部封装 系统/模块级封装

可以说,从函数 → 模块 → API,是功能封装粒度越来越大的过程。

通俗理解:不同"买菜方式"

可以用一个比喻来形象地理解它们:

  • C语言像超市自己搬货:你去超市买东西,得知道哪个货架在哪,手动挑选并结账(头文件 + 链接库)。
  • Python像点外卖:你说"我要牛奶",平台自动给你送来,不用关心它从哪来的(解释器动态导入模块)。
  • Java像公司采购:你申请一份需求,走审批流程,用标准接口对接供应商(类与接口,编译与JVM约束更严格)。

四、统一视角下的"调用模型"

JAVA、C、Python 是这样。那么我们格局打开:抽象所有调用方式,可以看到一个共同模型:

复制代码
[调用者] ------(通过接口)------> [被调用者的封装逻辑]

这个模型不依赖语言,不依赖调用方式。只要满足:

  • 清晰的调用入口(接口、函数、方法)
  • 明确的封装边界(实现不可见)
  • 调用和被调用的分离(你调用的是"黑盒")

那它就是一种"统一的调用机制"。是不是豁然开朗捏~

五、总结升华

​ 可能我的这篇博客在资深程序员看来,像极了在论证一个已知的常识。就像我写了2k字在论证人活着要呼吸一样。其实我的这个思考对于我自身来说是有很大意义的,也可以算个进步的开始,开始有想法了。学编程不只是会用语言,而是在理解语言的"灵魂"------这才是编程真正的魅力所在。最后用一句话作为结尾,送给我,也送给不断攀登的年轻人:

​ 青年人的血液应该是液态阳光!