6.2. 方法

自定义类型除了可以通过结构体达到对成员数据的封装外,最大的作用是它们可以拥有方法。在凹语言中,方法是一类特殊的、依附于特定类型的函数,见下例:

// 版权 @2023 凹语言 作者。保留所有权利。

type Info struct {
    name: string
    age:  i32
}

// 方法声明:
func Info.Print {
    println("名字:", this.name, ",年龄:", this.age)
}

func main {
    i := Info{name: "张三", age: 35}
    i.Print() // 名字: 张三 ,年龄: 35
}

方法声明一般形式如下:

func 类型名.方法名(参数列表) => (返回值列表) {方法函数体}

方法声明与普通全局函数声明的区别是函数名的部分增加了 类型名. 。在方法体内部,this 是方法所属类型的引用,通过 this. 可读写其成员。

如果仅从目前已介绍的语法来看,方法和全局函数可以完成同样的功能,比如上述例子和下面的代码几乎等价:

// 版权 @2023 凹语言 作者。保留所有权利。

type Info struct {
    name: string
    age:  i32
}

func Print(this: *Info) {
    println("名字:", this.name, ",年龄:", this.age)
}

func main {
    i := Info{name: "张三", age: 35}
    Print(&i) // 名字: 张三 ,年龄: 35
}

如上例所示,如果把全局函数的第一个参数设为自定义类型的引用,那么它的作用和方法几乎是一致的——事实上在凹语言中,从运行时层面看,方法就是首参数为自定义类型引用的函数。既然如此,那么为何要特意引入这一概念呢?原因有两个:

  1. 方法有助于聚合对象的功能;
  2. 接口 这一概念直接依赖于方法——类型的方法集合决定了它所实现的接口,第7章将对此进行介绍。

需要特别注意的是,按照凹语言语法,使用 func T.xxx()... 声明的方法并不属于类型 T,而是属于类型 *T——既 T 的引用;也就是说具名类型本身不能拥有方法,拥有方法的只能是具名类型的引用。