文章转载地址:https://www.flysnow.org/2017/04/06/go-in-action-go-embedded-type.html

嵌入类型或嵌套类型,这是一种可以把已有类型的声明嵌入到新的类型里的一种方式,这种功能对代码复用非常

重要

在其他语言中,有继承的概念,但是在 Go 语言中没有继承的概念,Go 提倡的代码复用的方式是组合,所以,这

也是嵌入类型的意义所在,组合不是继承,所以,Go 才会更加灵活

type Reader interface {
Read(p []byte) (n int, err error)
} type Writer interface {
Write(p []byte) (n int,err error)
} type Closer interface {
Close() error
} type ReadWriter interface {
Reader
Writer
} type ReadCloser interface {
Reader
Closer
} type WriteCloser interface {
Writer
Closer
}

  上面是标准 io 包里,我们常用的接口,可以看到 ReadWriter 接口是嵌入 Reader、Writer 接口组合而成的新接口,这样

我们就不用在重复的定义被嵌入接口的方法,直接通过嵌入就可以了。嵌入类型同样适用于结构体类型,看下面例子:

type user struct {
name string
email string
} type admin struct {
user
level string
}

  嵌入后,被嵌入的类型称之为内部类型,新定义的类型称之为外部类型,这里 user 就是内部类型,而 admin 是外部类型

通过嵌入类型,与内部类型相关的字段、方法、标识符等都会被外部类型所拥有,就像外部类型自己的一样,这样就达到了

代码快捷复用组合的目的

同时,外部类型还可以添加自己的方法,字段等,可以很方便的扩展外部类型的功能

type user struct {
name string
email string
} type admin struct {
user
level string
} func main() {
ad := admin{user{"张三","zhangsans@qq.com"},"管理员"}
fmt.Println("可以直接调用,名字是:",ad.name)
fmt.Println("也可以通过内部类型调用:",ad.user.name)
fmt.Println("但新增的属性只能直接调用:",ad.level)
}

  上面是嵌入类型的使用,在初始化的时候,我们采用的是字面值的方式,先初始化 user 这个内部类型,再初始化

新增的 level 属性

对于内部类型的属性和方法访问上,我们可以采用外部类型直接访问,也可以通过内部类型进行访问,但是我们为

外部类型新增方法属性字段,只能使用外部类型访问,因为内部类型没有这些

当然,外部类型也可以声明同名的字段或方法,来覆盖内部类型,这种情况方法比较多,以方法为例:

type user struct {
name string
email string
} type admin struct {
user
level string
} func (u user) sayHello() {
fmt.Println("Hello,I am a user")
} func (a admin) sayHello() {
fmt.Println("Hello,I am a admin")
} func main() {
ad := admin{user{"张三","zhangsans@qq.com"},"管理员"}
ad.user.sayHello()
ad.sayHello()
}

  内部类型 user 有一个 sayHello 方法,外部类型对其进行了覆盖,同名重写 sayHello,然后在 main 方法分别访问这两个

类型的方法,打印输出:

Hello,I am a user
Hello,I am a admin

    从上面的输出可以看出,方法 sayHello 被覆盖了

嵌入类型还有一个强大的地方就是:如果内部类型实现了某个接口,那么外部类型也被认为实现了这个接口,如下示例:

type Hello interface {
hello()
} type user struct {
name string
email string
} type admin struct {
user
level string
} func (u user) hello() {
fmt.Println("Hello, I am a user")
} func sayHello(h Hello) {
h.hello()
} func main() {
ad := admin{user{"张三","zhangsans@qq.com"},"管理员"}
sayHello(ad.user) // 使用 user 作为参数
sayHello(ad) // 使用 admin 作为参数
}

  新增一个 Hello 接口,然后让 user 类型实现这个接口,最后定义了一个 sayHello 方法,它接受一个 Hello 类型的

参数,最后我们在 main 函数调用的时候,发现不管是 user 类型吧,还是 admin 类型作为参数传递给 sayHello 都能正

常调用,这里就能说名 admin 接口实现了接口 Hello,但是又没有显示声明 admin 实现,所以这个实现是通过内部类型

user 实现的,因为 admin 包含了 user 所有方法和字段,所以也就实现了这个接口

最新文章

  1. noip2016十连测题解
  2. 【一】Ubuntu14.04+Jekyll+Github Pages搭建静态博客
  3. Eclipse 编译错误 Access restriction: The type 'JPEGCodec' is not API (restriction on required library 'C:\Program Files\Java\jre7\lib\rt.jar')
  4. 爬取知乎百万信息之UrlTask
  5. JavaScript高级程序设计57.pdf
  6. Swift - 给图片添加文字水印(图片上写文字,并可设置位置和样式)
  7. Swift编程语言学习4.1——周期
  8. 关于多字节字符入库失败处理(所谓的Emji),该处理是舍弃特殊字符
  9. Davinci DM6446开发攻略——LINUX GPIO驱动源码移植
  10. blfs(systemd版本)学习笔记-为桌面环境构建xorg服务
  11. HDU-1160.FatMouse'sSpeed.(LIS变形 + 路径打印)
  12. 解决Win8系统修改IP地址后保存不了的方法
  13. 解决Maven报Plugin execution not covered by lifecycle configuration
  14. 8.29 jQuery
  15. ms08_067攻击实验
  16. Less-Mixins分离规则集
  17. Get Started with ASP.NET Web API 2 (C#)
  18. struts2学习笔记(1)配置与基本操作
  19. BaseAdapter,SimpleAdapter,CursorAdapter的用法
  20. java实现发送邮件工具

热门文章

  1. Word操作——通配符
  2. 正则re
  3. PowerBI功能发布时间线
  4. 配置成功java11后安装eclipse失败
  5. 使用微软自带 SharpZipLib 进行多文件 压缩
  6. VS2017 + EF6连接MySql
  7. Pocket Gem OA: Log Parser
  8. GET和POST两种基本请求方法(转自博主--在途中#)
  9. [ISSUE] [Centos] Centos Start Nginx Show: Failed to start nginx.service:unit not found
  10. 从后台拿到echarts的数据值,求出百分比