# OOP

#### 结构体

```
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}
```

定义一个结构体实例（rust只允许整体可变或不可变）：

```
let user1 = User {
    email: String::from("someone@example.com"),
    username: String::from("someusername123"),
    active: true,
    sign_in_count: 1,
}; // immutable
let mut user1 = User {
    email: String::from("someone@example.com"),
    username: String::from("someusername123"),
    active: true,
    sign_in_count: 1,
}; // mutable
```

当使用某个变量初始化结构体的某个域，且这个变量的名字和这个域的名字一样时，初始化可以省略域的名字：

```
User {
    email,
    username,
    active: true,
    sign_in_count: 1,
}
```

从已有的一个结构体创建新结构体，可以使用如下的update语法：

```
let user2 = User {
    email: String::from("another@example.com"),
    username: String::from("anotherusername567"),
    ..user1
};
```

可以创建域操作类似于tuple的tuple struct（相当于一个定义了类名的tuple）：

```
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
```

结构体允许被定义为不含任何域。

结构体可以包含类型为引用的域，但需要借助lifetime机制。

可以使用`println!`打印结构体，但需要使用`{:?}`或者`{:#?}`格式化，并在结构体定义前面添加一行`#[derive(Debug)]`.

```
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!("rect1 is {:?}", rect1);
}
```

#### 方法

关键字为`impl`：

```
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}
```

方法的第一个参数一定是self，它可以让出所有权、给出可变引用或不可变引用（`self`,`&self`,`&mut self`）

如果不带上self参数就是关联函数（associated function），类似于C的静态函数：

```
impl Rectangle {
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}
```

调用时用双冒号，如`Rectangle::square(3)`.

同一个类的方法可以定义在多个`impl`块里。

#### enum枚举

最简单的形式：

```
enum IpAddrKind {
    V4,
    V6,
}
```

使用`IpAddrKind::V4`取值。

枚举变量可以被定义为和某类数据具有绑定关系：

```
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

enum IpAddr {
    V4(String),
    V6(String),
}

let home = IpAddr::V4(String::from("127.0.0.1"));
```

甚至枚举类型也可以定义方法，如对上面的Message：

```
impl Message {
	fn call(&self) {
		// method body would be defined here
	}
}
```

#### Option

特殊且常用的模板类：

```
enum Option<T> {
    Some(T),
    None,
}
```

编译器不会把Option类型自动转换为T类型。

枚举类需要使用match语法来处理。

#### match，pattern & if let

```
match expression {
	pattern => instructions,
	pattern => {
		instructions;
	}
}
```

一个match表达式实例：

```
match coin {
    Coin::Penny => {
        println!("Lucky penny!");
        1
    }
    Coin::Nickel => 5,
    Coin::Dime => 10,
    Coin::Quarter => 25,
}
```

为了提取枚举表达式中的数据，需要用到pattern语法：

```
#[derive(Debug)] // so we can inspect the state in a minute
enum UsState {
    Alabama,
    Alaska,
    // --snip--
}
enum Coin {
    Penny,
    Quarter(UsState),
}
match coin {
    Coin::Penny => 1,
    Coin::Quarter(state) => {
        println!("State quarter from {:?}!", state);
        25
    }
}
```

利用match和pattern可以完成对Option的处理：

```
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
```

match语句中可以使用`_`作为一个default分支：

```
let some_u8_value = Some(0u8);
match some_u8_value {
    Some(3) => println!("three"),
    _ => (), // ()表示什么都不做
}
```

上面的语句也可以用如下的`if let`代替：

```
if let Some(3) = some_u8_value {
    println!("three");
}
```

`if let`有一个备选的`else`分支：

```
let mut count = 0;
if let Coin::Quarter(state) = coin {
    println!("State quarter from {:?}!", state);
} else {
    count += 1;
}
```

#### modules封装

* **Packages:** A Cargo feature that lets you build, test, and share crates
* **Crates:** A tree of modules that produces a library or executable
* **Modules** and **use:** Let you control the organization, scope, and privacy of paths
* **Paths:** A way of naming an item, such as a struct, function, or module

#### 容器

**Vector**

```
let data =Vec::new();
let data:Vec<i32> =Vec::new();
let vec = vec![1,2,3];
let vec:Vec<i32> =vec![1,2,3];
let v = vec![0; 10]; // 10个0
v.push(3);
let val = v.pop();
let num = v[2]; // Supported by implementing Index & IndexMut traits
```

### 异常处理

#### expect

```
result.expect("error info");

match result {
    Ok(num) => num,
    Err(_) => continue, // _算是一个哑变量，可以捕捉任何值
}
```

#### assert断言

```
assert_eq!()
assert!()
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://deemolover.gitbook.io/log-os/programming-languages/rust/oop.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
