编程语言可以怎么分类

成为Unity客户端开发已经快3年了,意味着用了3年的C#,不过学生时代几乎啥语言都接触过,最近打算深入研究游戏引擎,使用Godot游戏引擎进行开发,它使用的是C++,但却发现,C++不像C#那样我只需要在乎逻辑怎么写,C++需要我考虑代码如何构建,使用类似CMake、Scons这种构建工具,因此我打算从头了解一遍编程语言,深入了解为什么会有这种差异。


编程语言分类

编程语言的分类方式多样,不同维度可以交叉组合。以下是主要分类方式及典型示例:


一、按执行方式分类

类别特点典型语言
编译型源代码 → 机器码(直接执行)C、C++、Rust、Go
解释型源代码 → 逐行解释执行Python、Ruby、JavaScript(传统)
混合型编译+解释(如JIT/AOT)Java(JVM JIT)、JavaScript(V8引擎)

二、按编程范式分类

范式核心思想典型语言
面向对象以对象为核心(封装、继承、多态)Java、C++、Python
函数式以函数为核心(不可变数据、高阶函数)Haskell、Scala、Erlang
过程式以过程/函数调用顺序为核心C、Pascal
逻辑式基于形式逻辑推理Prolog
脚本式轻量级、快速开发Python、Perl、Bash

三、按抽象级别分类

级别特点典型语言
低级语言接近硬件,需手动管理资源Assembly、C
高级语言抽象程度高,屏蔽硬件细节Python、Java、C#

四、按用途分类

领域特点典型语言
通用编程适用于多种场景Python、Java、C++
系统编程操作系统、驱动开发C、Rust、Zig
Web开发前端/后端开发JavaScript、PHP、Ruby
数据科学数据分析、机器学习Python、R、Julia
嵌入式资源受限设备C、Lua、MicroPython

五、按类型系统分类

类型系统特点典型语言
静态类型变量类型在编译时确定C++、Java、Rust
动态类型变量类型在运行时确定Python、JavaScript、Ruby
强类型禁止隐式类型转换Python、Haskell
弱类型允许隐式类型转换(如强制转换)JavaScript、PHP

六、按并发模型分类

模型特点典型语言
线程模型基于操作系统线程Java、C++(std::thread)
Actor模型通过消息传递实现并发Erlang、Akka(Scala)
协程模型轻量级用户态线程Go(goroutine)、Python(asyncio)

七、按运行环境分类

环境特点典型语言
独立运行直接生成可执行文件C、Go
虚拟机依赖需虚拟机/运行时环境Java(JVM)、C#(CLR)
浏览器环境运行在浏览器中JavaScript、TypeScript

八、按设计哲学分类

哲学特点典型语言
简洁性语法极简(如强制缩进)Python、Go
多范式支持支持多种编程范式Scala、F#
安全优先内存安全、无指针Rust、Go

总结:分类不是互斥的

  • 示例
    • Python:高级、解释型、动态类型、多范式(面向对象+函数式)。
    • Rust:系统级、静态类型、编译型、内存安全。
    • JavaScript:脚本式、动态类型、浏览器环境、多范式(事件驱动+函数式)。

实际选择语言时需综合考虑:

  1. 项目需求(性能、开发效率)
  2. 团队熟悉度
  3. 生态支持(库、工具链)

执行方式分类

编程语言按执行方式分类,主要分为编译型解释型混合型(如JIT)。这种分类源于计算机底层执行机制的差异,以及开发者对性能开发效率跨平台能力的权衡。以下是详细分类及其背后的逻辑:


一、编译型语言(Compiled Languages)

graph LR A[源代码: .cpp] --> B(预处理) B --> C(编译) C --> D(汇编) D --> E(链接) E --> F[可执行文件]

执行流程

  1. 编译:源代码通过编译器(如GCC、Clang)一次性转换为机器码(可执行文件)。
  2. 执行:直接由操作系统运行生成的二进制文件。

典型语言

C、C++、Rust、Go、Swift。

为何这样设计?

  1. 性能优先
    • 机器码直接由CPU执行,无需运行时解释,速度最快。
    • 适合系统级开发(如操作系统、游戏引擎)。
  2. 硬件控制
    • 编译器可优化内存管理(如手动内存分配)、寄存器分配等底层细节。
  3. 静态类型系统
    • 编译时检查类型错误(如C++的强类型),减少运行时崩溃风险。

代价

  • 跨平台性差:需为不同平台(Windows/Linux)编译不同二进制文件。
  • 开发效率低:编译时间长,修改代码后需重新编译。

二、解释型语言(Interpreted Languages)

graph LR A[源代码: .py] --> B(解释器逐行解析) B --> C[生成字节码: .pyc] C --> D[执行字节码]

执行流程

  1. 逐行解析:解释器(如Python解释器)逐行读取源代码。
  2. 即时翻译:将每行代码转换为中间表示(如字节码)或直接执行。

典型语言

Python、Ruby、JavaScript(传统浏览器环境)、Bash。

为何这样设计?

  1. 开发效率高
    • 无需编译步骤,修改代码后立即执行,适合快速迭代(如脚本任务)。
  2. 跨平台性强
    • 只需分发源代码,解释器负责适配不同平台(如Python的“一次编写,到处运行”)。
  3. 动态特性支持
    • 支持动态类型(运行时确定变量类型)、反射等灵活功能。

代价

  • 性能较低:逐行解释执行,无法充分利用硬件优化。
  • 启动时间长:大型脚本(如Python数据分析)可能因解释器初始化而变慢。

三、混合型语言(Hybrid Execution)

graph LR A[源代码: .java] --> B(编译) B --> C[生成字节码: .class] C --> D{运行时环境} D -->|首次执行| E[JIT编译为机器码] D -->|热点代码| F[直接执行机器码] E --> G[可执行程序] F --> G

核心模式

结合编译与解释的优势,常见两种实现:

  1. 即时编译(JIT, Just-In-Time)
    • 源代码先编译为中间字节码(如Java的.class),运行时由虚拟机(JVM)动态编译为机器码。
    • 典型语言:Java、C#、JavaScript(V8引擎)。
  2. AOT编译(Ahead-Of-Time)
    • 在运行前将源代码或中间代码编译为机器码,但不同于传统编译型语言(如Rust的LLVM优化)。
    • 典型语言:Swift、Rust。

为何这样设计?

  1. 平衡性能与跨平台
    • JIT在运行时优化热点代码(如Java的HotSpot JVM),接近编译型性能。
    • 字节码保持跨平台能力(如Java的“一次编译,到处运行”)。
  2. 动态优化
    • JIT可根据实际运行数据优化代码(如V8引擎对JS的优化)。

代价

  • 内存占用高:需同时维护字节码和JIT编译后的机器码。
  • 启动延迟:JIT初始化阶段可能影响性能(如Java应用冷启动较慢)。

四、分类的核心逻辑:性能 vs 灵活性

分类核心目标适用场景代表技术
编译型最大化执行效率操作系统、高频交易、游戏引擎C/C++、Rust
解释型开发效率与跨平台性脚本任务、Web后端、数据分析Python、JavaScript
混合型性能与灵活性的折中企业级应用、跨平台移动开发Java(JVM)、JavaScript(V8)

五、为什么会出现这些差异?

1. 硬件与操作系统的限制

  • 编译型语言直接操作硬件资源(如内存地址),但不同平台的指令集(x86/ARM)不同,导致代码无法通用。
  • 解释型语言通过虚拟机(如JVM)抽象硬件差异,实现跨平台。

2. 开发者的效率需求

  • 编译型语言需要手动管理内存和底层细节,适合有经验的开发者;
  • 解释型语言提供高级抽象(如自动垃圾回收),降低学习门槛。

3. 语言特性的复杂度

  • 动态类型、反射等特性难以在编译时完全优化,更适合解释执行(如Python的灵活性)。
  • 静态类型语言(如Rust)可通过编译时检查提前发现问题,提升安全性。

六、现代趋势:打破传统边界

  1. 编译型语言引入解释特性
    • Go语言通过go run直接解释执行代码,兼顾开发效率。
  2. 解释型语言引入JIT
    • JavaScript的V8引擎将代码编译为机器码,性能接近C++。
  3. 全栈语言的混合模式
    • TypeScript(编译为JS) + WebAssembly(AOT编译)结合两者的优势。

总结

编程语言的执行方式分类,本质是工程需求与硬件能力的博弈结果

  • 编译型:追求极致性能,牺牲灵活性。
  • 解释型:强调开发效率和跨平台,牺牲速度。
  • 混合型:在两者间寻找平衡,适应复杂场景。

选择建议

  • 开发系统级软件(如操作系统)→ C/C++
  • 快速构建Web应用 → JavaScript/Python
  • 需要跨平台且高性能 → Java(JVM)Rust

编程范式分类

编程语言按编程范式分类,常见的核心范式有以下四种。每种范式代表一种独特的代码组织逻辑和问题解决思路:


1. 面向对象编程(OOP)

核心思想

  • 将现实世界抽象为对象(包含数据和行为),通过封装隐藏细节、继承复用代码、多态实现灵活调用。
    典型语言:Java、C++、Python、C#
    适用场景
  • 大型系统(如GUI应用、游戏开发)
  • 需要模块化扩展的项目
    代码示例
1
2
3
4
5
6
7
8
// Java:继承与多态
class Animal {
    void sound() { System.out.println("叫声"); }
}
class Dog extends Animal {
    @Override
    void sound() { System.out.println("汪汪"); } // 多态
}

2. 函数式编程(FP)

核心思想

  • 函数为基本单元,强调纯函数(输入相同则输出相同)、不可变数据,避免副作用。
    典型语言:Haskell、Scala、JavaScript(部分支持)
    适用场景
  • 并发编程(无共享状态)
  • 数据处理(如Map/Reduce)
    代码示例
1
2
3
// JavaScript:纯函数(无副作用)
const add = (a, b) => a + b; 
const result = add(3, 5); // 始终返回8

3. 过程式编程

核心思想

  • 按步骤顺序执行函数,通过函数调用组织逻辑,数据与操作分离。
    典型语言:C、Pascal
    适用场景
  • 系统级开发(如操作系统内核)
  • 小型脚本工具
    代码示例
1
2
3
4
5
6
7
// C:过程式函数调用
#include <stdio.h>
void printHello() { printf("Hello"); }
int main() {
    printHello(); // 顺序执行
    return 0;
}

4. 事件驱动编程

核心思想

  • 事件(如点击、网络请求)触发响应,通过回调函数或事件循环处理异步操作。
    典型语言:JavaScript、Python(asyncio)
    适用场景
  • GUI应用、实时系统
  • 高并发服务(如Web服务器)
    代码示例
1
2
3
4
// JavaScript:事件监听
button.addEventListener('click', () => {
    console.log('按钮被点击!'); // 事件触发后执行
});

范式对比总结

范式核心单元典型场景关键优势
面向对象对象大型系统、模块化扩展代码复用(继承)、灵活性(多态)
函数式函数并发编程、数据处理无副作用、易于测试
过程式函数系统开发、小型工具简单直接、执行高效
事件驱动事件GUI应用、实时服务高响应性、资源利用率高

重要提示

  • 多范式融合:现代语言(如Python、JavaScript)通常支持多种范式。

    1
    2
    3
    4
    5
    
    # Python示例:混合OOP和函数式
    numbers = [1, 2, 3]
    squared = list(map(lambda x: x**2, numbers))  # 函数式
    class Calculator:  # 面向对象
        def square(self, x): return x**2
    
  • 选择建议

    • 开发商业系统 → 面向对象(Java/C#)
    • 高并发后端 → 函数式(Scala/Elixir)
    • 硬件操作 → 过程式(C/Rust)
    • 前端交互 → 事件驱动(JavaScript)

抽象级别分类

编程语言按抽象级别分类,核心依据是语言离硬件底层远近、对开发者的屏蔽程度和代码控制精细度。以下是三级分类详解:


一、低级语言(Low-Level Languages)

抽象特点

  • 直接映射硬件指令(如寄存器、内存地址)
  • 开发者需手动管理底层资源(内存分配、CPU指令)
    典型语言
  • 汇编语言(Assembly)
    • 直接对应机器码(如 MOV AX, 5 → 移动数字5到AX寄存器)。
    • 应用场景:操作系统内核开发、嵌入式设备驱动。
  • 机器语言(二进制代码)
    • 由0和1组成,CPU直接执行(如 10110000 00000101 → 将5存入寄存器)。

代码示例(x86汇编)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
section .data
    msg db 'Hello, World!', 0
section .text
    global _start
_start:
    mov eax, 4      ; 系统调用编号(sys_write)
    mov ebx, 1      ; 文件描述符(stdout)
    mov ecx, msg     ; 字符串地址
    mov edx, 13      ; 字符串长度
    int 0x80        ; 调用内核

二、中级语言(Mid-Level Languages)

抽象特点

  • 平衡控制与抽象:提供基础数据结构(数组、结构体)和流程控制(循环、条件),但仍暴露指针等底层操作。
  • 开发者需管理内存但可忽略指令集细节。
    典型语言
  • C语言
    • 直接操作内存指针(如 int *ptr = &a;)。
    • 应用场景:操作系统、硬件驱动、高性能计算(如Linux内核用C编写)。
  • C++(部分特性)
    • 支持面向对象(类、继承),但保留指针操作(如 int* p = new int(10);)。

代码示例(C语言指针操作)

1
2
3
4
5
6
7
#include <stdio.h>
int main() {
    int a = 10;
    int *p = &a;     // p指向a的内存地址
    printf("%d", *p); // 输出10(解引用)
    return 0;
}

三、高级语言(High-Level Languages)

抽象特点

  • 完全屏蔽硬件细节:自动内存管理(垃圾回收)、丰富的数据结构(字典、对象)。
  • 语法接近自然语言(如英语单词),开发效率高。
    典型语言
  • Python
    • 自动内存回收,无需声明变量类型(如 name = "Alice")。
  • Java
    • 虚拟机(JVM)屏蔽平台差异,自带垃圾回收。
  • JavaScript
    • 解释执行,浏览器/Node.js环境抽象底层操作。

代码示例(Python高级抽象)

1
2
3
# 列表推导式 + 自动内存管理
squares = [x**2 for x in range(10)]  
print(squares)  # [0, 1, 4, 9, ..., 81]

抽象级别对比总结

级别硬件依赖内存管理开发效率性能典型场景
低级语言直接依赖手动极低最高操作系统内核、驱动
中级语言间接依赖手动/半自动中等系统软件、游戏引擎
高级语言完全屏蔽自动中/低Web应用、数据分析、AI

关键说明

  1. 为什么C/C++属于中级?

    • C/C++允许直接操作内存(如指针),但又提供高级抽象(C++的类、模板),介于低级和高级之间
  2. 现代语言的混合抽象

    • Rust:高级语法(模式匹配、错误处理) + 低级控制(无垃圾回收,零成本抽象)。
    • Go:高级并发模型(goroutine) + 中级内存管理(手动释放资源)。
  3. 抽象级别的核心价值

    • 低级语言:极致性能 → 适合航空航天、高频交易。
    • 高级语言:快速开发 → 适合互联网应用、脚本工具。

选择建议

  • 开发硬件驱动 → C/汇编
  • 构建大型游戏引擎 → C++
  • 快速开发Web应用 → Python/JavaScript
Licensed under CC BY-NC-SA 4.0