Rust 概念

常量

  • 声明常量使用const, 声明变量使用let, 如果想要一个变量可变 加入关键字mut, 对于常量的命名规范: 大写加下划线,常量的声明周期是在整个程序的声明周期内都是有效的
  • 变量隐藏
    fn main(){
     let x = 5;
     let x = x + 1;
     {
       let x = x * 2
     }
  }

如上所示定义一个与之前同民的新变量,表示第一个变量被第二个变量shadowing
区别
1. 能够没有使用mut 标记变量重新赋值 不会有编译错误,但是返回变量还是不可变
2. 再一次使用let后 实际创建一个新变量,与mut不同修改变量的值和类型

		let space = "   ";
		let space = space.len(); // 但是如果变量使用 mut 修饰 会在此报错 修改变量类型

数据类型推断

Rust是静态语言必须在编译时候 知道所有变量类型, rust中两类数据自己标量复合

  • 对于 字符串转换成数字 使用 parse进行解析 和 JAVA类似
  • 元组与数组最大区别在于:元组不需要保证每一个元素的类型相同, 数组是属于栈上分配固定大小的单个内存模块
     let a:[i32; 5] = [1,2,3,4,5];
     变量名称a的数组包含5个元素
     let a = [3; 5] // 有5个元素初始化值为3
    

函数

RUST 代码中 使用fn 关键字 使用 snake_case 风格,小写_下划线
R语言中 函数签名中必须要声明每个函数的类型.

    语句 Vs 表达式
    语句: 执行一些操作但是没有返回值, 表达式: 计算一些结果值
    函数调用,宏调用,和{} 都是属于表达式
    let y = {
       let x = 3;
       x + 1 // 注意没有;
  };

通过判断是否有;为标准,有;是语句,无分号是表达式,比如上面表达式无分号但是 可以进行赋值

fn main() {
    let x = plus_one(5);
    println!("The value of x is: {}", x);
}
fn plus_one(x: i32) -> i32 {
    x + 1 // 注意没有分号 是一个表达式 有返回值,如果增加;赋值语句无返回值
}

& 引用

& 由于所有权的问题,在变量被赋值后原有变量的所有权会被消失,这样导致一个问题我们无法重复使用该变量, 如何解决变量在返回给调用函数后,我们还能够使用该变量, Rust语言提出一种 &引用的概念,表示我们只是借用但是不使用其所有权
在函数传参数时候 我们将一个对象的引用作为参数,避免使用所有权,因此当引用停止使用后,其指向值也不会被丢弃
引用是不能修改的,如果想要修改请使用可变引用 &mut a
有引用有解引用 使用运算符合是 *

fn main() {
    let s = String::from("hello world");
    let word = first_word(&s);
    println!("{}", word);
}

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..] // 找寻不到返回整个字符串没有; 直接返回
}

结构体

类似于C语言中结构体,JAVA中类对象一样, 在面向对象过程中有关联的变量组合到一起

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

fn main() {
     let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
     let mut user2 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

    user2.email = String::from("anotheremail@example.com");
}

  • 没有任何参数的类单元结构体
    作用: 某个类型上实现特性但是不关注类型中存储的数据
   struct AlwaysEqual;
   fn main() {
      let subject = AlwaysEqual;
}
  • 结构体程序
fn main() {
    let width1 = 30;
    let height1 = 50;

    println!(
        "The area of the rectangle is {} square pixels.",
        area(width1, height1)
    );
}

fn area(width: u32, height: u32) -> u32 {
    width * height
}
// rust 在设计时候 高内聚,低耦合,明显对于面积计算 width, hegiht 属于让此代码更加具有明确性和增加可读性的应用, 在area 签名上
// 变种一: 使用元组,虽然能够减少参数,但是有个问题无法知道参数的意义,容易混淆造成值的错误,在代码中没有表达数据的意图
// 变种2:结果体赋予数据更多意义
struct Rectangle {
	width: u32,
	height: u32,
}
fn main() {
	let rect = Rectangle {
		width: 30,
		height: 50,
   };
   println!("area of rectangle is {}", area(& rect))
}
fn area(rectangle &Rectangle) ->u32 {
	rectangle.width * rectangle*height // 表达式结果返回
}
  • trait派生增加使用功能
    rust 没有JAVA中继承概念,使用trait派生方式进行方法组合
    对于结构体要向先生 println!,
    1. 外部属性: #[derive(Debug)]
    2. {} ->{:?} 以DEBUG方式展示
      **增加属性来派生 Debug trait ,并使用调试格式打印Rectangle 实例删除线格式 **
    struct Rectangle {
    width: u32,
    height: u32,
}

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

    println!("rect1 is {}", rect1); // 报错 对于结构体无法使用Display个数
}
src\main.rs:12:29
   |
12 |     println!("rect1 is {}", rect1);
   |                             ^^^^^ `Rectangle` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `Rectangle`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
   -------
   #[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

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

    println!("rect1 is {:?}", rect1); // 更大的结构体使用 {:#?}
}

  1. 使用dbg! 宏 dbg!宏将输出结果打印到stderr, println! 输出结果到stdout, dbg! 接收一个表达式的所有权
   println!("rect1 is {:?}", rect1); // 通过stdout  标准输出控制流
    dbg!(&rect1); // 输出结果到stderr 标准错误输出控制流

后续对trait扩展 ,可以写自定义的trait

方法

方法和函数类似, 使用fn 关键字和名称什么, Python内部中CLass内的方法,函数 在Class外表示函数,方法前面带有self 标识, 第一个参数总是self, 代码使用该方法的结构体实例

   #[derive(Debug)]
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 is {}", rect1.area()); // 通过stdout  标准输出控制流
   
}

类似JAVA中getters 一样 与字段同名方法将被定义值返回字段中值,
C/C++ 中 ., -> 调用方法, .直接在对象上调用方法,-> 在一个对象的指针上调用方法,需要解引用指针 object是一个指针 object->someting() 等价于(*object).something()

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}
// can_hold方法 一个长方体是否能够包含另外一个长方体
fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };
    let rect2 = Rectangle {
        width: 10,
        height: 40,
    };
    let rect3 = Rectangle {
        width: 60,
        height: 45,
    };

    println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
    println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
}
  • 关联函数
    ** 不是方法的关联函数叫构造函数,:: 返回结构体新实例,类似JAVA中构造函数**
    所有在impl中定义的函数叫关联函数,如果定义一个不以self为第一个参数的关联函数,让其并不作用一个结果体的实例, 叫做不是方法的关联函数, 作用: 返回一个结构体的新实例构造函数 ,类似于JAVA的构造函数, 外部使用:: 调用这个构造函数
	impl Rectangle {
   fn square(size: u32) -> Rectangle { // 第一个参数不是self
       Rectangle {
           width: size,
           height: size,
       }
   }
}
  • 多个impl 块: 作用 主要运用于泛型和trait 派生上,有多个impl, 结构类似组合到一个impl, 派生在另外一个impl 块中
  • 总结:
    结构体让你可以创建出在你的领域中有意义的自定义类型。通过结构体,我们可以将相关联的数据片段联系起来并命名它们,这样可以使得代码更加清晰。在 impl 块中,你可以定义与你的类型相关联的函数,而方法是一种相关联的函数,让你指定结构体的实例所具有的行为
    结构体并不是创造自定义类型的唯一方法,枚举也可以创建自定义方法

枚举

使用场景在于使用过程遇到所有的IP类型 通过枚举出所有的可能值

    enum IpAddrKind {
  V4,
  V6
}
let four = IpAddrKind::V4;
fn main() {
  enum IpAddrKind {
      V4,
      V6,
  }

  struct IpAddr {
      kind: IpAddrKind,
      address: String,
  }

  let home = IpAddr {
      kind: IpAddrKind::V4,
      address: String::from("127.0.0.1"),
  };

  let loopback = IpAddr {
      kind: IpAddrKind::V6,
      address: String::from("::1"),
  };
}

-- 根据简洁方式:
fn main() {
  enum IpAddrKind {
      V4(String),
      V6(String),
  }
  
  let home = IpAddrKind::V4(String::from("127.0.0.1"));
}

将任意的类型的数据放入到枚举成员中,比如字符串,数字类型。或者其他枚举

enum Message {
  Quit,
  Move { x: i32, y: i32 },
  Write(String),
  ChangeColor(i32, i32, i32),
}
  • 枚举中定义方法
      impl Message{
	fn call(&self){
        
   }
}
let m = Message::Write(String::from("hello"));
m.call();
  • 介绍标准库中一个Option 枚举, 一个非常普通场景 一个值要么有值或者没有值, NULL值问题 当你尝试像一个非空值一样使用空值 会出现空指针异常,rust中没有空值,但是有一个有和无的概念
    有点类似于JAVA8 中Option这个泛型工具类
 return Optional.ofNullable(user)
                   .map(u-> u.getAddress())
                   .map(a->a.getCity())
                   .orElseThrow(()->new Exception("取指错误"));

match匹配

rust 有一个叫做 match的的控制流运算符,允许将一个值与一系列的模式向比较得到匹配的执行向队员代码,match来源于模式的表现力以及编译器。
match 与if最大区别在于match匹配任何类型,if只能是boolean, => 将模式与代码分开
注意: match 会按照顺序依次匹配,类似JAVA switch

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}
  • 与rust 核心代码中 Option
fn main() {
 // 编写代码获取Option<i32>,其中包含值+1,无返回空值
    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);
}

other 表示其他类型 类似JAVA中switch default

  • 总结: match 结合枚举类一起适用于很多场景
  • if let 简单控制流
    if let 语法让我们不再冗长结合 if 和 let, if let 是match 一个语法糖
    当值匹配某一模块执行代码,但是忽略其他模块, 不能使用match 的穷尽性检查
  let mut count = 0;
    match coin {
        Coin::Quarter(state) => println!("State quarter from {:?}!", state),
        _ => count += 1, // 其他格式全部加1
    }
 let mut count = 0;
    if let Coin::Quarter(state) = coin {
        println!("State quarter from {:?}!", state);
    } else {
        count += 1;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值