背景
之前的文章咱们现已介绍了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。