第十章:组织与文档
级别 2 — 认知
跨文件组织程序:接口、实现和文档。
适合放在一个文件中的程序是脚本。跨越数十个文件的程序是系统。本章介绍 C 如何将代码组织为接口和实现,以及 Auto 的模块系统如何提供更清晰的替代方案。
10.1 接口文档
在 C 中,接口声明在头文件(.h)中,实现位于源文件(.c)中。头文件就是契约:
c
// geometry.h — 接口
#ifndef GEOMETRY_H
#define GEOMETRY_H
typedef struct {
float width;
float height;
} Rectangle;
float Rectangle_area(Rectangle r);
float Rectangle_perimeter(Rectangle r);
#endifc
// geometry.c — 实现
#include "geometry.h"
float Rectangle_area(Rectangle r) {
return r.width * r.height;
}
float Rectangle_perimeter(Rectangle r) {
return 2.0f * (r.width + r.height);
}需要 Rectangle 的其他文件包含该头文件:
c
// main.c
#include "geometry.h"
#include <stdio.h>
int main(void) {
Rectangle r = {4.0f, 6.0f};
printf("Area: %f\n", Rectangle_area(r));
return 0;
}文档注释。 C 使用 /** ... */ 编写文档。许多项目采用类似 Doxygen 的约定:
c
/**
* @brief 计算矩形的面积。
* @param r 矩形
* @return 面积(float)
*/
float Rectangle_area(Rectangle r);Auto 的方法。 Auto 用 mod 和 use 系统替代头文件。类型及其关联函数构成天然接口:
auto
// geometry.at — 接口和实现合二为一
type Rectangle {
width float
height float
}
fn Rectangle.new(w float, h float) Rectangle {
Rectangle(w, h)
}
fn Rectangle.area(r Rectangle) float {
r.width * r.height
}
fn Rectangle.perimeter(r Rectangle) float {
2.0 * (r.width + r.height)
}另一个文件使用 use 引入模块:
此示例依赖多文件模块,不能在书页内运行——请到 Playground
auto
// main.at
use geometry
fn main() {
let r Rectangle = Rectangle.new(4.0, 6.0)
print("Area:", r.area(r))
}