|
|
|
@ -2,7 +2,7 @@
|
|
|
|
|
|
|
|
|
|
行百里者半五十,欢迎大家来到这里,虽然还不到中点,但是已经不远了。如果说之前学的基础数据类型是原子,那么本章将讲的数据类型可以认为是分子。
|
|
|
|
|
|
|
|
|
|
本章的重点在复合类型上,顾名思义,复合类型是由其它类型组合而成的,最典型的就是结构体 `struct` 和枚举 `enum`。例如平面上的一个点 `point(x,y)`,它由两个数值类型的值 `x` 和 `y` 组合而来。我们不想单独去维护这两个数值,因为单独一个 `x` 或者 `y` 是含义不完整的,无法标识平面上的一个点,应该把它们看作一个整体去理解和处理。
|
|
|
|
|
本章的重点在复合类型上,顾名思义,复合类型是由其它类型组合而成的,最典型的就是结构体 `struct` 和枚举 `enum`。例如平面上的一个点 `point(x,y)`,它由两个数值类型的值 `x` 和 `y` 组合而来。我们无法单独去维护这两个数值,因为单独一个 `x` 或者 `y` 是含义不完整的,无法标识平面上的一个点,应该把它们看作一个整体去理解和处理。
|
|
|
|
|
|
|
|
|
|
来看一段代码,它使用我们之前学过的内容来构建文件操作:
|
|
|
|
|
```rust
|
|
|
|
@ -31,7 +31,7 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
接下来我们的学习非常类似原型设计:有的方法只提供 API 接口,但是不提供具体实现。此外,有的变量在声明之后并未使用,因此在这个阶段我们需要排除一些编译器噪音(Rust 在编译的时候会扫描代码,变量声明后未使用会以 `warning` 警告的形式进行提示),引入 `#![allow(unused_variables)]` 属性标记,该标记会告诉编译器忽略未使用的变量,不要抛出 `warning` 警告,具体的常见编译器属性你可以在这里查阅:[编译器属性标记](../../compiler/attributes.md).
|
|
|
|
|
|
|
|
|
|
`read` 函数也非常有趣,它返回一个 `!`,这个表明该函数是一个发散函数,不会返回任何值,包括 `()`。`unimplemented!()` 告诉编译器该函数尚未实现,`unimplemented!()` 标记通常意味着我们期望快速完成主要代码,回头再通过搜索这些标记来完成次要代码,类似的标记还有 `todo!()`,当代码执行到这种未实现的地方时,程序会直接报错: 你可以反注释 `read(&mut f1, &mut vec![]);` 这行,然后再观察下结果。
|
|
|
|
|
`read` 函数也非常有趣,它返回一个 `!` 类型,这个表明该函数是一个发散函数,不会返回任何值,包括 `()`。`unimplemented!()` 告诉编译器该函数尚未实现,`unimplemented!()` 标记通常意味着我们期望快速完成主要代码,回头再通过搜索这些标记来完成次要代码,类似的标记还有 `todo!()`,当代码执行到这种未实现的地方时,程序会直接报错。你可以反注释 `read(&mut f1, &mut vec![]);` 这行,然后再观察下结果。
|
|
|
|
|
|
|
|
|
|
同时,从代码设计角度来看,关于文件操作的类型和函数应该组织在一起,散落得到处都是,是难以管理和使用的。而且通过 `open(&mut f1)` 进行调用,也远没有使用 `f1.open()` 来调用好,这就体现出了只使用基本类型的局限性:**无法从更高的抽象层次去简化代码**。
|
|
|
|
|
|
|
|
|
|