Go结构体嵌入接口类型

原创
2017/11/03 15:44
阅读数 7.1K

Go结构体——嵌入接口

Go结构体——嵌入结构体
https://my.oschina.net/xinxingegeya/blog/709203

在结构体(struct)中内嵌接口(interface),定义如下接口

// 接口:一组方法的集合
// OpenCloser 接口定义两个方法 返回 error
type OpenCloser interface {
	Open() error
	Close() error
}

定义如下结构体,内嵌了接口 OpenCloser,

type AutoDoor struct {
	OpenCloser   // 匿名接口
	delay int    // 延迟多长时间开启
	msg   string // 自动开启时的警报
}

当初始化结构体AutoDoor时,需要传入一个实现此接口OpenCloser的结构体赋值,所以定义如下结构体,

type Door struct {
	open bool // 门的状态是否开启
	lock bool // 门的状态是否上锁
}

func (d *Door) Open() error {
	fmt.Println("door open...")
	d.open = true
	return nil
}

func (d *Door) Close() error {
	fmt.Println("door close...")
	d.open = false
	return nil
}

当初始化 AutoDoor 结构体时,

door := &AutoDoor{&Door{false, false}, 3, "warning"}

传入的是一个 Door 结构体的指针类型。

完整的程序如下,

package main

import (
	"fmt"
	"time"
	"strconv"
)

// 接口:一组方法的集合
// OpenCloser 接口定义两个方法 返回 error
type OpenCloser interface {
	Open() error
	Close() error
}

//type Locker interface {
//	Lock() error
//	Unlock() error
//}

type Door struct {
	open bool // 门的状态是否开启
	lock bool // 门的状态是否上锁
}

func (d *Door) Open() error {
	fmt.Println("door open...")
	d.open = true
	return nil
}

func (d *Door) Close() error {
	fmt.Println("door close...")
	d.open = false
	return nil
}

type AutoDoor struct {
	OpenCloser   // 匿名接口
	delay int    // 延迟多长时间开启
	msg   string // 自动开启时的警报
}

func (a *AutoDoor) Open() error {
	fmt.Println("Open after " + strconv.Itoa(a.delay) + " seconds")
	time.Sleep(time.Duration(a.delay) * time.Second)
	fmt.Println("Door is opening:" + a.msg)
	return nil
}

func main() {
	door := &AutoDoor{&Door{false, false}, 3, "warning"}
	door.Open()
	if v, ok := door.OpenCloser.(*Door); ok { //类型断言
		fmt.Println(v)
	}

	door.OpenCloser.Open()
	if v, ok := door.OpenCloser.(*Door); ok { //类型断言
		fmt.Println(v)
	}

	door.Close()
	if v, ok := door.OpenCloser.(*Door); ok { //类型断言
		fmt.Println(v)
	}

}

运行如下,

Open after 3 seconds
Door is opening:warning
&{false false}
door open...
&{true false}
door close...
&{false false}

注意的是,AutoDoor 并未定义Close 方法,而是通过内嵌接口的方式获得了该方法。

下面是 Go 语言中内部类型方法集提升的规则:

http://golang.org/ref/spec#Method_sets
https://www.goinggo.net/2014/05/methods-interfaces-and-embedded-types.html

给定一个结构体类型 S 和一个命名为 T 的类型,方法提升像下面规定的这样被包含在结构体方法集中:

如果 S 包含一个匿名字段 T,S 和 *S 的方法集都包含接受者为 T 的方法提升。

这条规则说的是当我们嵌入一个类型,嵌入类型的接受者为值类型的方法将被提升,可以被外部类型的值和指针调用。

对于 *S 类型的方法集包含接受者为 *T 的方法提升

这条规则说的是当我们嵌入一个类型,可以被外部类型的指针调用的方法集只有嵌入类型的接受者为指针类型的方法集,也就是说,当外部类型使用指针调用内部类型的方法时,只有接受者为指针类型的内部类型方法集将被提升。

如果 S 包含一个匿名字段 *T,S 和 *S 的方法集都包含接受者为 T 或者 *T 的方法提升

这条规则说的是当我们嵌入一个类型的指针,嵌入类型的接受者为值类型或指针类型的方法将被提升,可以被外部类型的值或者指针调用。

这就是语言规范里方法提升中仅有的三条规则,根据这个推导出一条规则:

如果 S 包含一个匿名字段 T,S 的方法集不包含接受者为 *T 的方法提升。

这条规则说的是当我们嵌入一个类型,嵌入类型的接受者为指针的方法将不能被外部类型的值访问。

=========END=========

展开阅读全文
Go
打赏
1
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
1
分享
返回顶部
顶部