English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
En Rust, las estructuras (Struct) y los tuplos (Tuple) pueden agrupar varios tipos de datos que no necesariamente son iguales en un todo, pero cada miembro de la estructura y la estructura en sí tienen un nombre, por lo que al acceder a sus miembros no es necesario recordar los índices. Los tuplos se utilizan comúnmente para la transmisión de múltiples valores no definidos, mientras que las estructuras se utilizan para estructurar estructuras de datos comunes. Cada miembro de la estructura se llama "campo".
Esta es una definición de estructura:
struct Site { domain: String, name: String, nation: String, found: u32 }
Nota: si usas a menudo C/C++Recuerda que en Rust, la declaración struct se utiliza solo para definir, no para declarar ejemplos, no se requiere el símbolo ; al final, y cada campo definido debe separarse con ,.
Rust en muchos aspectos está influenciado por JavaScript, al definir estructuras de ejemplo se utiliza la sintaxis de clave: valor de los objetos JSON para implementar:
let w3codebox = Site { domain: String::from("es.oldtoolbag.com"); name: String::from("w3codebox), nation: String::from("China"); found: 2013 };
如果你不了解 JSON 对象,你可以不用管它,记住格式就可以了:
结构体类名 { 字段名 : 字段值, ... }
这样的好处是不仅使程序更加直观,还不需要按照定义的顺序来输入成员的值。
如果正在示例化的结构体有字段名称和现存变量名称一样的,可以简化书写:
let domain = String::from("es.oldtoolbag.com"); let name = String::from("w3codebox); let w3codebox = Site { domain, // 等同于 domain : domain, name, // 等同于 name : name, nation: String::from("China"); traffic: 2013 };
有这样一种情况:你想要新建一个结构体的示例,其中大部分属性需要被设置成与现存的一个结构体属性一样,仅需更改其中的一两个字段的值,可以使用结构体更新语法:
let site = Site { domain: String::from("es.oldtoolbag.com"); name: String::from("w3codebox), ..w3codebox };
注意:..w3codebox 后面不可以有逗号。这种语法不允许一成不变的复制另一个结构体示例,意思就是说至少重新设定一个字段的值才能引用其他示例的值。
有一种更简单的定义和使用结构体的方式:元组结构体。
元组结构体是一种形式是元组的结构体。
与元组的区别是它有名字和固定的类型格式。它存在的意义是为了处理那些需要定义类型(经常使用)又不想太复杂的简单数据:
struct Color(u8, u8, u8); struct Point(f64, f64); let black = Color(0, 0, 0); let origin = Point(0.0, 0.0);
“颜色”和“点坐标”是常用的两种数据类型,但如果示例化时写个大括号再写上两个名字就为了可读性牺牲了便捷性,Rust 不会遗留这个问题。元组结构体对象的使用方式和元组一样,通过 . 和下标来进行访问:
fn main() { struct Color(u8, u8, u8); struct Point(f64, f64); let black = Color(0, 0, 0); let origin = Point(0.0, 0.0); println!("black = ({}, {}, {}),", black.0, black.1, black.2); println!("origin = ({}, {}),", origin.0, origin.1); }
Resultado de la ejecución:
black = (0, 0, 0) origin = (0, 0)
La estructura debe controlar la propiedad de los valores de los campos, porque cuando la estructura se desecha, se liberan todos los campos.
Por eso en los ejemplos de este capítulo se utiliza el tipo String en lugar de &str.
Esto no significa que no se defina campos de tipo referencia en la estructura, lo que se debe implementar a través del mecanismo de 'vida' (lifetimes).
Pero es difícil explicar el concepto de 'vida' (lifetimes) aquí, por lo que se explicará en capítulos posteriores.
En la depuración, es muy útil mostrar completamente un ejemplo de estructura. Pero si lo escribimos manualmente, puede ser muy incómodo. Por lo tanto, Rust proporciona un método conveniente para salida completa de una estructura:
[derive(Debug)] struct Rectángulo { anchura: u32, altura: u32, } fn main() { let rect1 = Rectángulo { anchura: 30, altura: 50}; println!("rect1 es {:?}", rect1); }
Como se muestra en la primera línea: es necesario importar la biblioteca de depuración [derive(Debug)] Después de eso, se puede usar el marcador de posición {:?} en macros println y print para salida de una estructura completa:
rect1 es Rectangle { width: 30, altura: 50}
Si hay muchos atributos, se puede usar otro marcador de posición {:#?} .
Resultados de salida:
rect1 es Rectangle { width: 30, height: 50 }
El método (Method) es similar a una función (Function), pero se utiliza para operar con ejemplos de estructuras.
Si ha estudiado algunos lenguajes orientados a objetos, seguro que sabe que los métodos generalmente se colocan dentro de la definición de la clase y se usa 'this' para representar el ejemplo operado.
El lenguaje Rust no es orientado a objetos, esto se puede ver en su innovador mecanismo de propiedad. Sin embargo, se pueden implementar pensamientos valiosos de la programación orientada a objetos en Rust.
El primer parámetro de un método de estructura debe ser &self, no se necesita declarar el tipo, ya que 'self' no es un estilo, sino una palabra clave.
Calcular el área de un rectángulo:
struct Rectángulo { anchura: u32, altura: u32, } impl Rectángulo { fn area(&self) -> u32 { self.width * self.height } } fn main() { let rect1 = Rectángulo { anchura: 30, altura: 50}; println!("rect1's área es {}", rect1.area()); }
Resultados de salida:
rect1's área es 1500
Tenga en cuenta que no es necesario escribir 'self' al llamar a métodos de la estructura, ya que es una consideración de conveniencia.
Un ejemplo de instancia con múltiples parámetros:
struct Rectángulo { anchura: u32, altura: u32, } impl Rectángulo { fn area(&self) -> u32 { self.width * self.height } fn wider(&self, rect: &Rectangle) -> bool {}} self.anchura > rect.anchura } } fn main() { let rect1 = Rectángulo { anchura: 30, altura: 50}; let rect2 = Rectángulo { anchura: 40, altura: 20}; println!("{}", rect1.wider(&rect2)); }
Resultado de la ejecución:
false
Este programa calcula rect1 ¿Es más amplia que rect2 más amplia.
La razón por la que "método de estructura" no se llama "función de estructura" es porque el nombre "función" se reserva para este tipo de función: no tiene el parámetro &self en el impl bloque.
Este tipo de función no depende del ejemplo, pero para usarla se debe declarar en qué impl bloque se encuentra.
El función de String::from que siempre se ha utilizado es una "función asociada".
[derive(Debug)] struct Rectángulo { anchura: u32, altura: u32, } impl Rectángulo { fn create(anchura: u32, altura: u32) -> Rectángulo { Rectángulo { anchura, altura } } } fn main() { let rect = Rectangle::create(30, 50); println!("{:?}", rect); }
Resultado de la ejecución:
Rectángulo { anchura: 30, altura: 50}
Consejo:El bloque impl de la estructura se puede escribir varias veces, lo que tiene el mismo efecto que la concatenación de su contenido!
Las estructuras pueden estar solo como un símbolo sin necesidad de cualquier miembro:
struct UnitStruct;
Llamamos a esta estructura sin cuerpo una estructura de unidad (Unit Struct).