结构体

作者: BIGHAI | 来源:发表于2017-06-16 21:05 被阅读0次

    你可能注意到null类型不在此列。他比较特殊,typeof对它的处理存在问题:typeof null === "object"返回真,但是正确的结果应该是"null"的,这个JavaScript内部的bug由来已久——已经存在了20多年,对于这个特性,因为牵扯到太多的web系统,“修复”它会产生更过的bug,令太多的系统短时间内无法工作。

    结构体是一个创建更复杂数据类型的方法。普通结构体的定义无需在末尾使用“;”,使用结构体来定义一个变量应该使用下面这样的形式:结构体名{字段名:值},为字段赋值的顺序不需要和声明时保持一致。结构体变量可以使用.字段名来访问那个字段名所对应的值。

    fn main(){
      let origin:Point = Point{x: 0, y: 0};
      println!("{}", origin.x);//0
      println!("{}", origin.y);//0
    }
    struct Point{
      x: i32,
      y: i32
    }
    

    1.结构体不支持字段可变性

    mut关键字是用来修饰借用以及绑定的。目前为止,rust在语言级别上还不支持字段可变性,所以如果你想像下面这样写的话那么会报错。

    struct Foo{
      mut x: i32//语法错误
    }
    

    尽管不支持字段可变性,但是rust可以通过其他诡异的方法来使得字段的值得到改变。如下所示:

    fn main(){
      let mut point:Point = Point{x: 1,y: 2};
      point.x = 2;
      println!("{}", point.x);
    }
    struct Point{
      x: i32,
      y: i32
    }
    

    上面的这个方法:我们明明是定义了一个可变的绑定,然而到最后我们却能够改变的结构体变量的字段的值,要知道这之间是不存在什么逻辑之间的因果关系的,对于近乎完美的rust来说这无疑是一点不足。而且要注意的是如果我们的的结构体变量自身并不是一个可变的绑定的话,那么修改字段的值将会报错。
    尽管如此,但是由于mut可以修饰借用,所以结构体中的字段的值也可以是一个可变的借用。这个时候可以达到间接修改字段的值的问题。如下所示:

    fn main(){
      let num:&mut i32 = &mut 9;
      let foo:Foo = Foo{n: num};
      *foo.n = 99;
      println!("{}", *foo.n);//99
    }
    struct Foo<'a>{
      n: &'a mut i32
    }
    

    2.更新语法

    如果我们在构造同一个结构体的另一个对象的时候希望能够利用这个结构体先前所构造出来的对象的某些字段,那么可以使用更新语法:在早前的结构体变量前面加上..

    下面可以看一个例子:

    fn main(){
      let point:Point = Point{x: 0, y: 1, z: 0};
      let origin:Point = Point{y: 0, ..point};
      println!("{} {} {}", origin.x, origin.y, origin.z);//0 0 0
    }
    struct Point{
      x: i32,
      y: i32,
      z: i32
    }
    impl Point{
      fn get_x(&self) -> i32{self.x}
      fn get_y(&self) -> i32{self.y}
      fn get_z(&self) -> i32{self.z}
    }
    

    需要注意的问题,更新语法必须用在同一个类型的结构体上,比如说下面的这个例子就是错误的:

    //error[E0308]: mismatched types
    fn main(){
      let point:Point = Point{x: 1, y: 1, z: 1};
      let color:RGB = RGB{x: 0, ..point}; //expected struct `RGB`, found struct `Point`
    }
    struct Point{
      x: i32,
      y: i32,
      z: i32
    }
    impl Point{
      fn get_x(&self) -> i32{self.x}
      fn get_y(&self) -> i32{self.y}
      fn get_z(&self) -> i32{self.z}
    }
    struct RGB{
      x: i32,
      y: i32,
      z: i32
    }
    

    3.元组结构体

    Rust中有一个数据类型的表示方法很像元组和结构体的混合体,正由于这个特点我们叫他为元组结构体。元组结构体的表示方法如下所示:struct 元组结构体名();注意这里必须使用;对于普通的结构体来说我们并不需要使用 ;来结尾,但是对于元组结构体来说,我们必须使用;来结尾,而且对于元组结构体来说它不需要字段名,但是需要字段的数据类型。下面举一个例子:

    fn main(){
      struct Color(i32, i32, i32);
      let color:Color = Color(255, 255, 255);
      println!("{} {} {}", color.0, color.1, color.2);//255 255 255
      let Color(mut r, mut g, mut b) = color;
      println!("{} {} {}", r, g, b);//255 255 255
      r = 0;
      println!("{} {}", r, color.0);//0 255
    }
    

    从 上面的例子我们可以看出:元组结构体可以像元组一样使用“.位置”来得到那个位置处的值,同时也可以let解构来获得每个项的值,同时利用let解构的方法需要注意。

    4.类单元结构体

    类单元结构体即是在结构体中没有使用任何字段。至于类单元结构体有什么作用的话目前也还不清楚。

    fn main(){
      struct EmptyStruct{};//定义类单元结构体的方法一
      struct EmptyStruct2;//定义类单元结构体的方法二
      let empty1 = EmptyStruct{};//必须使用{}
      let empty2 = EmptyStruct2;//不需要使用{}
      //Error: let empty3 = EmptyStruct;
    }
    

    END

    相关文章

      网友评论

          本文标题:结构体

          本文链接:https://www.haomeiwen.com/subject/scbmqxtx.html