MoonBit 语言导览 MoonBit

方法

在 MoonBit 里,方法是关联到某个类型上的顶层函数。

有两种方式来定义方法:

  • fn method_name(self : T, ..) -> ..。第一个参数的名字必须是 self,定义出来的方法会被关联到类型 T
  • fn T::method_name(..) -> ..,定义出来的方法会被关联到类型 T

和普通函数相比,方法可以用更灵活的方式来调用:

  • 所有方法都可以用 T::method_name(..) 的形式调用
  • 方法也可以用 x.method_name(..) 的形式调用,假设 x 的类型是 T,这种写法等价于 T::method_name(x, ..)
  • fn method_name(self : T, ..) 形式声明的方法可以像普通函数一样直接用 method_name(..) 的形式调用

之前的章节中已经出现了很多方法,例如 Array::make(..)array.length()

关于方法的两种定义方式的不同之处是什么,应该如何选择:

  • fn method_name(self : T, ..) 声明的方法就是一个普通的顶层函数,所以它可以像普通函数一样直接调用。但这也意味着它不能和其他函数重名。如果一个方法是给它所在的包的一个比较主要的类型定义的,并且不会和其他函数重名,则推荐用 fn method_name(self : T, ..) 的形式定义它,这样用户调用时可以省去 T::
  • fn T::method_name(..) 声明的方法会被放到 T 这个小命名空间里,所以这种方法只能用 T::method_name(..) 或者 x.method_name(..) 的方式调用。但相应的,这种方法可以和普通函数以及其他类型的方法重名。所以,这种定义方式可以用来解决名字冲突或简化包的顶层作用域。
type MyInt Int

fn increment(self : MyInt) -> MyInt {
  MyInt(self._ + 1)
}

fn MyInt::println(x : MyInt) -> Unit {
  println("MyInt(\{x._})")
}

fn main {
  let x = MyInt(39)
  let y = x.increment() // 用 `.` 语法调用方法
  let z = increment(y) // `fn increment(..)` 可以直接调用
  let w = MyInt::increment(z) // 也可以用 `T::method_name` 调用
  w.println()
  MyInt::println(w) // `fn MyInt::println` 不能直接用 `println(..)` 调用
}