背景

之前的文章咱们现已介绍了Move的模块和函数,接下来将会介绍一些Move的特性。

结构体

结构体是用户自界说的具有复杂数据的数据类型,它能够简单理解为一个key——value方式的存储器,key时存储数据的姓名而value是其存储的值。

结构体的界说

结构体只能在模块里界说,一struct关键字最初,之后时姓名和双括号,双括号里边是是界说:

struct Name {
  FIELD1: TYPE1,
  FIELD@: TYPE2,
  ......
}

以下就是结构体界说的例子:

module M {
  struct Empty{}
  struct MyStruct{
    field1: address,
    field2: bool,
    field3: Empty
  }
  struct Example {
    field1: u8,
    field2: address,
    field3: u64,
    field4: bool,
    field5: bool,
    field5: MyStruct
  }
}

需求注意的是每一个界说的结构体都会变成一个新的类型,这个类型能够桶模块拜访,如M::MyStruct。

递归界说在Move是不答应的,例如以下代码编译会报错:

struct MyStruct{
    field5: MyStruct
  }

结构体的运用

咱们能够经过创立实例来运用结构体,能够经过它的界说来创立实例:

module Country {
  struct Country {
    id: u8,
    population: u64
  }
  public fun new_country(c_id: u8, c_population: u64): Country {
    let country = Country {
      id: c_id,
      population: c_population
    };
    country
  }
}

Move还答应运用更简洁的方式创立实例:

// ...
public fun new_country(id: u8, population: u64): Country {
    // id matches id: u8 field
    // population matches population field
    Country {
        id,
        population
    }
    // or even in one line: Country { id, population }
}

拜访结构体的特点

只有模块内部才干拜访结构体的特点,对于模块外部,结构体的特点是不可见的:

// ...
public fun get_country_population(country: Country): u64 {
    country.population // <struct>.<property>
}

结构结构体

能够经过let = 去解构一个结构体

module Country {
    // ...
    // we'll return values of this struct outside
    public fun destroy(country: Country): (u8, u64) {
        // variables must match struct fields
        // all struct fields must be specified
        let Country { id, population } = country;
        // after destruction country is dropped
        // but its fields are now variables and
        // can be used
        (id, population)
    }
}

需求注意的是未运用的变量在Move中是被禁止的,如果解构结构体又不需求运用其特点,需求运用下划线:

module Country {
    // ...
    public fun destroy(country: Country) {
        // this way you destroy struct and don't create unused variables
        let Country { id: _, population: _ } = country;
        // or take only id and don't init `population` variable
        // let Country { id, population: _ } = country;
    }
}

之前提到外部的模块是无法直接拜访结构体的特点的,所以为了外部模块能够拜访界说的结构体的特点,需求提供相关的拜访函数:

module Country {
    struct Country {
        id: u8,
        population: u64
    }
    public fun new_country(id: u8, population: u64): Country {
        Country {
            id, population
        }
    }
    // don't forget to make these methods public!
    public fun id(country: &Country): u8 {
        country.id
    }
    // don't mind ampersand here for now. you'll learn why it's 
    // put here in references chapter 
    public fun population(country: &Country): u64 {
        country.population
    }
    // ... fun destroy ... 
}

Abilities

Move有一个十分灵活且可高度定制化的类型体系,每一个类型都能够被赋予四种才能去决定数据怎么被运用、删除活存储,这四种才能如下:

  • Copy-能够被仿制

  • Drop-能够在结尾被删除

  • Key-能够被全局存储设置为key

  • Store-能够被全局存储

    这篇文章会介绍Copy和Drop的才能,至于Key和Store才能在之后的文章详细介绍。在界说结构体的时候能够设置这四种才能:

    module Library {
    struct Book has store, copy, drop {
      year: u64
    }
    struct Storage has {
      books: vector<Book>
    }
    struct Empty{}
    

}

如果没有设置这几种特点会怎么样呢:

odule Country {
struct Country {
id: u8,
population: u64
}

public fun new_country(id: u8, population: u64) {
Country(id, population)
}
}

script {
use {{sender}}::Country;

fun main() {
Country::new_country(1, 1000000);
}
}

我嘛在Country中界说了一个结构体,然后经过一个方法暴露给外部,然后在外部调用这个方法来获取数据,但是返回值没有被运用,因为咱们没有给这个结构体设置Drop特点,这时候不会主动丢掉返回值,会报错

error:
┌── scripts/main.move:5:9 ───

5 │ Country::new_country(1, 1000000);
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot ignore values without the ‘drop’ ability. The value must be used

#### Drop
咱们能够经过has Drop给结构体设置Drop才能

module Country {
struct Country has drop { // has
id: u8,
population: u64
}
// …
}

当咱们设置了Drop才能,脚本就能运行了:

script {
use {{sender}}::Country;

fun main() {
    Country::new_country(1, 1000000); // value is dropped
}   

}

> Drop只界说Drop的才能,解构不需求Drop才能。
#### Copy
咱们现已学习了怎么创立一个Country实例以及丢掉它,那么咱们该怎么实现复制呢,Move提供来copy关键字来实现复制,前提是需求现已赋予结构体copy才能。

module Country {
struct Country has drop, copy { // see comma here!
id: u8,
population: u64
}
// …
}

script {
use {{sender}}::Country;

fun main() {
    let country = Country::new_country(1, 1000000);
    let _ = copy country;
}   

}

### 最后,这篇文章咱们首要介绍了Move的结构体与类型体系的四种才能,更多文章能够重视QStack。