Rust 学习指南 - Rust 高级结构

649 阅读5分钟
原文链接: www.codemore.top
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!
}