English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

结构体 Rust

Dans Rust, les structures (Struct) et les tuples (Tuple) peuvent regrouper ensemble plusieurs types de données différents pour former un ensemble, mais chaque membre et la structure elle-même ont un nom, ce qui permet d'accéder aux membres sans se souvenir des indices. Les tuples sont souvent utilisés pour transmettre des valeurs multiples non définies, tandis que les structures sont utilisées pour structurer des données courantes. Chaque membre d'une structure est appelé "champ".

Définition de structure

Voici une définition de structure :

struct Site {
    domain : String,
    name : String,
    nation : String,
    trouvé : u32
}

Attention : si vous utilisez souvent C/C++Rappelez-vous que dans Rust, la déclaration struct est utilisée uniquement pour définir et non pour déclarer des exemples. Il n'est pas nécessaire de placer un point-virgule à la fin, et chaque champ doit être séparé par une virgule.

Exemple de structure

Rust est fortement influencé par JavaScript, en ce qui concerne la définition des structures, il utilise la syntaxe key: value des objets JSON pour implémenter :

let w3codebox = Site {
    domain: String::from("fr.oldtoolbag.com,),
    name: String::from("w3codebox,),
    nation: String::from("China"),
    found: 2013
};

如果你不了解 JSON 对象,你可以不用管它,记住格式就可以了:

结构体类名 {
    字段名 : 字段值 ,
    ...
}

这样的好处是不仅使程序更加直观,还不需要按照定义的顺序来输入成员的值。

如果正在示例化的结构体有字段名称和现存变量名称一样的,可以简化书写:

let domain = String::from("fr.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("fr.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);
}

运行结果:

black = (0, 0, 0)
origin = (0, 0)

Propriété de structure

Une structure doit maîtriser la propriété des valeurs de champ, car une structure est libérée de tous les champs lorsqu'elle est désactivée.

C'est pourquoi les exemples de cette section utilisent le type String plutôt que &str.

Cela ne signifie pas que les champs de structure ne définissent pas de champs de type de référence, ce qui doit être réalisé par le mécanisme de "durée de vie".

Mais il est difficile de décrire le concept de "durée de vie" pour le moment, donc il ne peut être expliqué que dans les chapitres suivants.

Sortie de structure

En mode débogage, il est très utile de visualiser complètement un exemple de structure. Mais si nous l'écrivons manuellement, cela sera très不便. C'est pourquoi Rust fournit une méthode pratique pour sortir une structure entière :

[[derive(Debug)]]
struct Rectangle {
    width: u32,
    height: u32,
}
fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };
    println!("rect1 est {:?}", rect1);
}

Comme le montre la première ligne : il est nécessaire d'importer la bibliothèque de débogage [[derive(Debug)]] Après cela, vous pouvez utiliser le symbole de remplacement {:?} dans les macros println et print pour sortir une structure entière :

rect1 est Rectangle { width: 30, height: 50 }

Si il y a plusieurs attributs, vous pouvez utiliser un autre symbole de remplacement {:#?} .

Résultat de la sortie :

rect1 est Rectangle {
    width: 30,
    height: 50
}

Méthodes de structure

Les méthodes (Method) et les fonctions (Function) sont similaires, mais elles sont utilisées pour opérer des exemples de structures.

Si vous avez appris quelques langages orientés objet, vous devez être très clair que les fonctions sont généralement placées dans la définition de la classe et représentées par this pour l'exemple opéré.

Le langage Rust n'est pas orienté objet, comme le montre l'innovation de son mécanisme de propriété. Mais les idées précieuses de l'orientation objet peuvent être réalisées en Rust.

Le premier paramètre d'une méthode de structure doit être &self, sans déclaration de type, car self n'est pas un style mais un mot-clé.

Calculer la surface d'un rectangle :

struct Rectangle {
    width: u32,
    height: u32,
}
    
impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}
fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };
    println!("rect1's area est {}", rect1.area());
}

Résultat de la sortie :

rect1's area est 1500

Veuillez noter que lors de l'appel d'une méthode de structure, il n'est pas nécessaire de saisir self, c'est pour des raisons de commodité.

Un exemple de plusieurs paramètres :

struct Rectangle {
    width: u32,
    height: u32,
}
impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
    fn wider(&self, rect: &Rectangle) -> bool {}}
        self.width > rect.width
    }
}
fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };
    let rect2 = Rectangle { width: 40, height: 20 };
    println!("{}", rect1.wider(&rect2));
}

运行结果:

false

这个程序计算 rect1 是否比 rect2 更宽。

关联函数结构体

之所以"结构体方法"不叫"结构体函数"是因为"函数"这个名字留给了这种函数:它在 impl 块中却没有 &self 参数。

这种函数不依赖示例,但是使用它需要声明是在哪个 impl 块中的。

一直使用的 String::from 函数就是一个"关联函数"。

[[derive(Debug)]]
struct Rectangle {
    width: u32,
    height: u32,
}
impl Rectangle {
    fn create(width: u32, height: u32) -> Rectangle {
        Rectangle { width, height }
    }
}
fn main() {
    let rect = Rectangle::create(30, 50);
    println!("{:?}", rect);
}

运行结果:

Rectangle { width: 30, height: 50 }

贴士:结构体 impl 块可以写几次,效果相当于它们内容的拼接!

单元结构体

结构体可以只作为一种象征而无需任何成员:

struct UnitStruct;

我们称这种没有身体的结构体为单元结构体(Unit Struct)。