Vector
在rust中,数组是由固定大小的,无法进行扩展,所以如果需要动态大小的数组则需要使用Vec<T> 。Vec是一个反省类型,T可以是是任何类型,例如Vec<i32>,其数据会分配到堆上。
//Creating vectors - 2 ways
let mut a = Vec::new(); //1.with new() keyword
let mut b = vec![]; //2.using the vec! macro
//Creating with data types
let mut a2: Vec<i32> = Vec::new();
let mut b2: Vec<i32> = vec![];
let mut b3 = vec![1i32, 2, 3];//sufixing 1st value with data type
//Creating with data
let mut b4 = vec![1, 2, 3];
let mut b5: Vec<i32> = vec![1, 2, 3];
let mut b6 = vec![1i32, 2, 3];
let mut b7 = vec![0; 10]; //ten zeroes
//Accessing and changing exsisting data
let mut c = vec![5, 4, 3, 2, 1];
c[0] = 1;
c[1] = 2;
//c[6] = 2; can't assign values this way, index out of bounds
println!("{:?}", c); //[1, 2, 3, 2, 1]
//push and pop
let mut d: Vec<i32> = Vec::new();
d.push(1); //[1] : Add an element to the end
d.push(2); //[1, 2]
d.pop(); //[1] : : Remove an element from the end
// Capacity and reallocation
let mut e: Vec<i32> = Vec::with_capacity(10);
println!("Length: {}, Capacity : {}", e.len(), e.capacity()); //Length: 0, Capacity : 10
// These are all done without reallocating...
for i in 0..10 {
e.push(i);
}
// ...but this may make the vector reallocate
e.push(11);
Vec 可以以以下三种方式遍历:
let mut v = vec![1, 2, 3, 4, 5];
for i in &v {
println!("A reference to {}", i);
}
for i in &mut v {
println!("A mutable reference to {}", i);
}
for i in v {
println!("Take ownership of the vector and its element {}", i);
}
struct
struct 的作用是将相关的属性放到统一的数据类型中。 rust中主要有三种struct
- C-like的struct
- 元组 struct
- unit struct
C-like struct
struct Color {
red: u8,
green: u8,
blue: u8
}
fn main() {
// creating an instance
let black = Color {red: 0, green: 0, blue: 0};
// accessing it's fields, using dot notation
println!("Black = rgb({}, {}, {})", black.red, black.green, black.blue); //Black = rgb(0, 0, 0)
// structs are immutable by default, use `mut` to make it mutable but doesn't support field level mutability
let mut link_color = Color {red: 0,green: 0,blue: 255};
link_color.blue = 238;
println!("Link Color = rgb({}, {}, {})", link_color.red, link_color.green, link_color.blue); //Link Color = rgb(0, 0, 238)
// copy elements from another instance
let blue = Color {blue: 255, .. link_color};
println!("Blue = rgb({}, {}, {})", blue.red, blue.green, blue.blue); //Blue = rgb(0, 0, 255)
// destructure the instance using a `let` binding, this will not destruct blue instance
let Color {red: r, green: g, blue: b} = blue;
println!("Blue = rgb({}, {}, {})", r, g, b); //Blue = rgb(0, 0, 255)
// creating an instance via functions & accessing it's fields
let midnightblue = get_midnightblue_color();
println!("Midnight Blue = rgb({}, {}, {})", midnightblue.red, midnightblue.green, midnightblue.blue); //Midnight Blue = rgb(25, 25, 112)
// destructure the instance using a `let` binding
let Color {red: r, green: g, blue: b} = get_midnightblue_color();
println!("Midnight Blue = rgb({}, {}, {})", r, g, b); //Midnight Blue = rgb(25, 25, 112)
}
fn get_midnightblue_color() -> Color {
Color {red: 25, green: 25, blue: 112}
}
Tuple struct
struct Color (u8, u8, u8);
struct Kilometers(i32);
fn main() {
// creating an instance
let black = Color (0, 0, 0);
// destructure the instance using a `let` binding, this will not destruct black instance
let Color (r, g, b) = black;
println!("Black = rgb({}, {}, {})", r, g, b); //black = rgb(0, 0, 0);
//newtype pattern
let distance = Kilometers(20);
// destructure the instance using a `let` binding
let Kilometers(distance_in_km) = distance;
println!("The distance: {} km", distance_in_km); //The distance: 20 km
}
unit struct
struct Electron;
fn main() {
let x = Electron;
}
enum
enum 可以包含多个变量,例如
enum Day {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
enum 变量同样可以指定不同的类型,例如:
enum FlashMessage {
Success, //a unit variant
Warning{ category: i32, message: String }, //a struct variant
Error(String) //a tuple variant
}
fn main() {
let mut form_status = FlashMessage::Success;
print_flash_message(form_status);
form_status = FlashMessage::Warning {category: 2, message: String::from("Field X is required")};
print_flash_message(form_status);
form_status = FlashMessage::Error(String::from("Connection Error"));
print_flash_message(form_status);
}
fn print_flash_message(m : FlashMessage) {
// pattern matching with enum
match m {
FlashMessage::Success =>
println!("Form Submitted correctly"),
FlashMessage::Warning {category, message} => //Destructure, should use same field names
println!("Warning : {} - {}", category, message),
FlashMessage::Error(msg) =>
println!("Error : {}", msg)
}
}
典型的enum的应用可以参考Optional
泛型
Rust中的泛型表示和其他语言例如Java类似
// generalizing functions
//-----------------------
fn takes_anything<T>(x: T) { // x has type T, T is a generic type
}
fn takes_two_of_the_same_things<T>(x: T, y: T) { // both x and y has same type
}
fn takes_two_things<T, U>(x: T, y: U) { // multiple types
}
// generalizing structs
//---------------------
struct Point<T> {
x: T,
y: T,
}
fn main() {
let point_a = Point { x: 0, y: 0 }; // T is a int type
let point_b = Point { x: 0.0, y: 0.0 }; // T is a float type
}
// When addding an implementation for a generic struct, the type parameters should be declared after the impl as well
// impl<T> Point<T> {
// generalizing enums
//-------------------
enum Option<T> {
Some(T),
None,
}
enum Result<T, E> {
Ok(T),
Err(E),
}
对于Optional和Result是Rust标准库中的,使用如下:
//01 - - - - - - - - - - - - - - - - - - - - - -
fn getIdByUsername(username: &str) -> Option<usize> {
return Some(userId);
}
struct Task {
title: String,
assignee: Option<Person>,
}
fn main() {
let username = "anonymous"
match getIdByUsername(username) {
None => println!("User not found"),
Some(i) => println!("User Id: {}", i)
}
}
fn get_word_count_from_file(file_name: &str) -> Result<u32, &str> {
return Err("File can not be found!")
Ok(word_count)
}
fn main() {
let mut file_name = "file_a";
match get_word_count_from_file(file_name) {
Ok(i) => println!("Word Count: {}", i),
Err(e) => println!("Error: {}", e)
}
}
Trait 和 impl
trait 类似于Java中的接口,trait可以定义其他类型需要实现的方法,一个类型可以实现多个方法,trait同样可以包含方法的默认实现,默认实现可以在具体实现中被覆盖。
struct Player {
first_name: String,
last_name: String,
}
impl Player {
fn full_name(&self) -> String {
format!("{} {}", self.first_name, self.last_name)
}
}
fn main() {
let player_1 = Player {
first_name: "Rafael".to_string(),
last_name: "Nadal".to_string(),
};
println!("Player 01: {}", player_1.full_name());
}
struct Player {
first_name: String,
last_name: String,
}
trait FullName {
fn full_name(&self) -> String;
}
impl FullName for Player {
fn full_name(&self) -> String {
format!("{} {}", self.first_name, self.last_name)
}
}
fn main() {
let player_2 = Player {
first_name: "Roger".to_string(),
last_name: "Federer".to_string(),
};
println!("Player 02: {}", player_2.full_name());
}
trait Foo {
fn bar(&self);
fn baz(&self) { println!("We called baz."); }
}
trait From<T> {
fn from(T) -> Self;
}
impl From<u8> for u16 {
}
impl From<u8> for u32{
}
对于&self,&mut self, self,表示对当前对象的引用,如果方法中没有self,则被称作是关联方法,使用::调用,
struct Player {
first_name: String,
last_name: String,
}
impl Player {
fn new(first_name: String, last_name: String) -> Player {
Player {
first_name : first_name,
last_name : last_name,
}
}
fn full_name(&self) -> String {
format!("{} {}", self.first_name, self.last_name)
}
}
fn main() {
let player_name = Player::new("Serena".to_string(), "Williams".to_string()).full_name();
println!("Player: {}", player_name);
}
trait 同样可也可继承其他trait
trait Person {
fn full_name(&self) -> String;
}
trait Employee : Person { //Employee inherit from person trait
fn job_title(&self) -> String;
}
trait ExpatEmployee : Employee + Expat { //ExpatEmployee inherit from Employee and Expat traits
fn additional_tax(&self) -> f64;
}
trait 使用的动态匹配
trait GetSound {
fn get_sound(&self) -> String;
}
struct Cat {
sound: String,
}
impl GetSound for Cat {
fn get_sound(&self) -> String {
self.sound.clone()
}
}
struct Bell {
sound: String,
}
impl GetSound for Bell {
fn get_sound(&self) -> String {
self.sound.clone()
}
}
fn make_sound<T: GetSound>(t: &T) { //T should be implemeted from GetSound trait
println!("{}!", t.get_sound())
}
fn main() {
let kitty = Cat { sound: "Meow".to_string() };
let the_bell = Bell { sound: "Ding Dong".to_string() };
make_sound(&kitty); // Meow!
make_sound(&the_bell); // Ding Dong!
}