# Rust 自定义类型

在我们常规使用 Rust 的自定义类型中，一般就是使用 struct 和 enum 。 

(当你学习到 Rust 的 unsafe 的高级操作之后，可以按自己的意愿构造任何数据类型，甚至可以精细到控制每一个 bit.)

Enum 就是枚举，当你需要从有限的几个选项中针对一种情况操作，或针对每一个选项分别操作，就是用它。

而 struct (结构体) 的使用更是极其广泛。总的来说，struct 是将若干个数据组合在一起表示成一个结构化的数据。比如我们想要构造一个数据结构，表示坐标中的一个点,就是有 x 和 y 坐标，可以使用学习过的原生数据类型浮点 f64，将两个浮点数组合起来: 

```rust
struct Point {
    x: f64,
    y: f64,
}
```

构造好一个结构体数据类型后，可以给它加上一些操作这些数据的方法，也就是函数。一般使用 impl 语法：

```rust
impl Point {
    fn new() -> Point { ... }
}
```


而对于我们后面会学习到的闭包，rust 编译器实际上会将它改写成一个 struct 。 比如一条直线的方程，y = 2x + 3, 写成闭包形式就是 |x| 2x + 3 ，具体代码形式如下：

```rust
let a = 2.0;
let b = 3.0;
let y = |x| a * x + b;
```

Rust 编译器会将它改写成(这里只是演示，为了简洁有所省略)：

```rust
struct SomeUnknownType {
    a: f64,
    b: f64,
}

impl SomeUnknownType {
    fn call(&self, x: f64) -> f64 {
        self.a * x + self.b
    }
}

let y = SomeUnknownType { a: 2.0, b: 3.0 };

y.call(x)
```

下面构造一个长方形并求面积的程序，错误的是：

## 答案

```rust

struct Point {
    x: f64,
    y: f64
}

struct Rectangle {
    Point,
    Point,
}

fn main() {
    let rec = Rectangle {
        { x: 1.0, y: 1.0 },
        { x: 3.0, y: 4.0 },
    };
    
    let width = rec.2.x - rec.1.x;
    let height = rec.2.y - rec.1.y;
    
    let s = width * height;
    
    println!("长方形的宽: {}, 高: {}, 面积: {}", width, height, s);
}
```



## 选项


### 定义结构体, 数据在主函数中操作

```rust

struct Point {
    x: f64,
    y: f64
}

struct Rectangle {
    top_left_point: Point,
    bottom_right_point: Point,
}

fn main() {
    let rec = Rectangle {
        top_left_point: Point { x: 1.0, y: 1.0 },
        bottom_right_point: Point { x: 3.0, y: 4.0 },
    };
    
    let width = rec.bottom_right_point.x - rec.top_left_point.x;
    let height = rec.bottom_right_point.y - rec.top_left_point.y;
    
    let s = width * height;
    
    println!("长方形的宽: {}, 高: {}, 面积: {}", width, height, s);
}

```


### 定义结构体, 以及相应的 impl 函数

```rust

struct Point {
    x: f64,
    y: f64,
}

struct Rectangle {
    top_left_point: Point,
    bottom_right_point: Point,
}

impl Rectangle {    
    fn width(&self) -> f64 {
        self.bottom_right_point.x - self.top_left_point.x
    }
    
    fn height(&self) -> f64 {
        self.bottom_right_point.y - self.top_left_point.y
    }
    
    fn area(&self) -> f64 {
        (self.bottom_right_point.x - self.top_left_point.x) * (self.bottom_right_point.y - self.top_left_point.y)
    }
}

fn main() {
    let rec = Rectangle {
        top_left_point: Point { x: 1.0, y: 1.0 },
        bottom_right_point: Point { x: 3.0, y: 4.0 },
    };
    
    let width = rec.width();
    let height = rec.height();
    
    let s = rec.area();
    
    println!("长方形的宽: {}, 高: {}, 面积: {}", width, height, s);
}

```

### 使用 Tuple Struct

```rust

struct Point{
    x: f64,
    y: f64,
}

struct Rectangle(Point, Point);

impl Rectangle {
    fn width(&self) -> f64 {
        self.1.x - self.0.x
    }
    
    fn height(&self) -> f64 {
        self.1.y - self.0.y
    }
    
    fn area(&self) -> f64 {
        self.width() * self.height()
    }
}

fn main() {
    let rec = Rectangle(Point{x: 0.0, y: 0.0}, Point{x: 3.0, y: 4.0});
    
    let width = rec.width();
    let height = rec.height();
    
    let s = rec.area();
    
    println!("长方形的宽: {}, 高: {}, 面积: {}", width, height, s);
}

```

<!-- ref:
https://doc.rust-lang.org/rust-by-example/custom_types/structs.html
https://stevedonovan.github.io/rustifications/2018/08/18/rust-closures-are-hard.html -->