Skip to main content

Move method

基本语法

<expression> . <identifier> <[type_arguments],*> ( <arguments> )

模块中定义

模块中定义方法:当该类型是函数中的第一个参数时,编译器将自动为其类型的声明创建方法别名

module a::m {
public struct X() has copy, drop, store;
public fun foo(x: &X) { ... } // 第一个参数是结构体类型,会自动将其定义为结构体类型的方法
public fun bar(flag: bool, x: &X) { ... } // 第一个参数不是结构体类型
}


fun example(x: a::m::X) {
x.foo(); // valid
// x.bar(true); ERROR!
}

use 函数别名

use fun <function> as <type>.<method alias>;

module a::cup {
public struct Cup<T>(T) has copy, drop, store;

public fun cup_borrow<T>(c: &Cup<T>): &T {
&c.0
}

public fun cup_value<T>(c: Cup<T>): T {
let Cup(t) = c;
t
}

public fun cup_swap<T: drop>(c: &mut Cup<T>, t: T) {
c.0 = t;
}
}



module b::example {
use fun a::cup::cup_borrow as Cup.borrow; // cup_borrow 接收参数第一个是一个结构体类型参数,所以可以被定义为方法
use fun a::cup::cup_value as Cup.value; // cup_borrow 接收参数第一个是一个结构体类型参数,所以可以被定义为方法
use fun a::cup::cup_swap as Cup.set; // cup_borrow 接收参数第一个是一个结构体类型参数,所以可以被定义为方法

fun example(c: &mut Cup<u64>) {
let _ = c.borrow(); // resolves to a::cup::cup_borrow
let v = c.value(); // resolves to a::cup::cup_value
c.set(v * 2); // resolves to a::cup::cup_swap
}
}





// use fun 中的 <function> 不必是完全解析的路径,可以使用别名代替,因此上面示例中的声明可以等效地写为
use a::cup::{Self, cup_swap};

use fun cup::cup_borrow as Cup.borrow;
use fun cup::cup_value as Cup.value;
use fun cup_swap as Cup.set;
module b::example {

fun double(c: &Cup<u64>): Cup<u64> {
let v = c.value();
Cup::new(v * 2)
}

}



fun double_double(c: Cup<u64>): (Cup<u64>, Cup<u64>) {
use fun b::example::double as Cup.dub;
(c.dub(), c.dub()) // resolves to b::example::double in both calls
}

use fun 第一个参数类型

use fun 可以在任何范围内创建,但 use fun 的目标 <function> 的第一个参数必须是 <type>

第一个参数类型 非构体类型

public struct X() has copy, drop, store;

fun new(): X { X() }
fun flag(flag: bool): u8 { if (flag) 1 else 0 }

use fun new as X.new; // ERROR!
use fun flag as X.flag; // ERROR!
// Neither `new` nor `flag` has first argument of type `X` 第一个参数的类型都不是X

第一个参数类型 是构体类型

public struct X() has copy, drop, store;

public fun by_val(_: X) {}
public fun by_ref(_: &X) {}
public fun by_mut(_: &mut X) {}

// All 3 valid, in any scope
use fun by_val as X.v;
use fun by_ref as X.r;
use fun by_mut as X.m;

public use 函数别名

a::cup::Cup.borrowa::cup::Cup.cup_borrow 的公共方法别名。两者都解析为 a::cup::cup_borrow 。两者都是“公共”的,因为它们可以在 a::cup 之外使用,而无需额外的 use 或 use fun 。

module a::cup {
public struct Cup<T>(T) has copy, drop, store;
// public use
public use fun cup_borrow as Cup.borrow;
public fun cup_borrow<T>(c: &Cup<T>): &T {
&c.0
}
}



module b::example {

fun example<T: drop>(c: a::cup::Cup<u64>) {
c.borrow(); // resolves to a::cup::cup_borrow
c.cup_borrow(); // resolves to a::cup::cup_borrow
}
}

别名交互

作用域

use fun 语句的作用域是其声明的范围。在范围内,使用别名的函数调用将解析为别名的函数。

也就是说:别名函数可以被覆盖

module a::m {
public struct X() has copy, drop, store;
public fun foo(_: &X) {}
public fun bar(_: &X) {}
}

module b::other {
use a::m::X;
use fun a::m::foo as X.f;

fun example(x: &X) {
x.f(); // resolves to a::m::foo
{
use fun a::m::bar as X.f; // 原文,这里错误
x.f(); // resolves to a::m::bar
};
x.f(); // still resolves to a::m::foo
{
use fun a::m::bar as X.f;
x.f(); // resolves to a::m::bar
}
}
}

自动借用

是什么

  1. 可变引用,可以自动借用(降级处理?),不可变引用必须显式借用
  2. 局部变量必须标记为 mut 以允许 &mut 借用

为什么

alt text

示例 1 无嵌套单个结构体

module a::m {
public struct X() has copy, drop;
public fun by_val(_: X) {}
public fun by_ref(_: &X) {}
public fun by_mut(_: &mut X) {}

fun example(mut x: X) {
x.by_ref(); // resolves to a::m::by_ref(&x)
x.by_mut(); // resolves to a::m::by_mut(&mut x) 局部变量必须标记为 mut 以允许 &mut 借用
}
}

示例 2 结构体为另一个结构体的字段

module a::m {
public struct X() has copy, drop;
public fun by_val(_: X) {}
public fun by_ref(_: &X) {}
public fun by_mut(_: &mut X) {}

public struct Y has drop { x: X }

fun example(mut y: Y) {
y.x.by_ref(); // resolves to a::m::by_ref(&y.x)
y.x.by_mut(); // resolves to a::m::by_mut(&mut y.x) 局部变量必须标记为 mut 以允许 &mut 借用
}
}

示例 3 没有引用

如果未借用值,则可能会移动或复制该值。

module a::m {
public struct X() has copy, drop;
public fun by_val(_: X) {}
public fun by_ref(_: &X) {}
public fun by_mut(_: &mut X) {}

public struct Y has drop { x: X }
public fun drop_y(y: Y) { y }

fun example(y: Y) {
y.x.by_val(); // copies `y.x` since `by_val` is by-value and `X` has `copy`
y.drop_y(); // moves `y` since `drop_y` is by-value and `Y` does _not_ have `copy`
}
}

链式调用

是什么

alt text

为什么可以

  1. 编译器会对链式调用进行特殊处理,将其转换为正常的函数调用链
  2. 编译器会对正常函数做处理:第一个参数是结构体类型,自动为其创建方法别名