GO语言实战之嵌入类型和属性隐私定义

举报
山河已无恙 发表于 2023/09/28 21:19:45 2023/09/28
【摘要】 1写在前面嗯,学习GO,所以有了这篇文章博文内容为《GO语言实战》读书笔记之一主要涉及知识:嵌入类型/隐私性标识符的作用理解不足小伙伴帮忙指正 对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》2嵌入类型Go 语言 允许用户扩展或者修改已...

1写在前面


  • 嗯,学习GO,所以有了这篇文章
  • 博文内容为《GO语言实战》读书笔记之一
  • 主要涉及知识:嵌入类型/隐私性标识符的作用
  • 理解不足小伙伴帮忙指正

对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》


2嵌入类型

Go 语言 允许用户扩展或者修改已有类型的行为。在修改已有类型以符合新类型的时候也很重要。这个功能是通过 嵌入类型(type embedding) 完成的,嵌入类型是将已有的类型直接声明在新的结构类型里。被嵌入的类型被称为新的外部类型的内部类型

通过嵌入类型,与内部类型相关的标识符会提升到外部类型上

这里嵌入类型,即有面向对象中继承的味道,内部类的相关标识会提升到外部类型上,即类似面向对象中的继承,子类会继承父类的方法和属性。会涉及到重写隐藏

golang 本质上是没有继承相关语法和概念,相对于 Java 来讲,不同的是 支持多继承,可以同时嵌入多个内部类型。而且外部类型也没有对内部类型的引用。没有 super 的概念. 在整体设计上,有种 Java 内部类继承了一个和外部类无关的类的感觉

本质上 嵌入类型是一种组合关系,合成复用原则,没有继承那种强关系。

package main

import (
 "fmt"
)
type user struct {
 name  string
 email string
}

type user1 struct {
 name1 string
 name2 string
}

func (u *user) notify() {
 fmt.Printf("Sending user email to %s<%s>\n",
  u.name,
  u.email)
}
type admin struct {
 user  // Embedded Type
 user1
 level string
}
func main() {
 ad := admin{
  user: user{
   name:  "john smith",
   email: "john@yahoo.com",
  },
  level: "super",
 }
 ad.user.notify()
 // 借助内部类型提升,notify 方法也可以直接通过 ad 变量来访问
 ad.notify()
}

直接通过外部类型的变量来调用 notify 方法,由于内部类型的标识符提升到了外部类型,我们可以直接通过外部类型的值来访问内部类型的标识符,类似面向对象中的继承

func main() {
 ad := admin{
  user: user{
   name:  "john smith",
   email: "john@yahoo.com",
  },
  level: "super",
 }

 sendNotification(&ad)
}

func sendNotification(n notifier) {
 n.notify()
}

如果外部类型并不需要使用内部类型的实现,就需要重写,在外部类型中重写内部类型的绑定的方法,这对于内部类型被称之为隐藏

package main

import (
 "fmt"
)

type notifier interface {
 notify()
}
type user struct {
 name  string
 email string
}
func (u *user) notify() {
 fmt.Printf("Sending user email to %s<%s>\n",
  u.name,
  u.email)
}
type admin struct {
 user
 level string
}
func (a *admin) notify() {
 fmt.Printf("Sending admin email to %s<%s>\n",
  a.name,
  a.email)
}
func main() {
 ad := admin{
  user: user{
   name:  "john smith",
   email: "john@yahoo.com",
  },
  level: "super",
 }
 sendNotification(&ad)
 ad.user.notify()
 ad.notify()
}
func sendNotification(n notifier) {
 n.notify()
}

3公开或未公开的标识符

要想设计出好的 API,需要使用某种规则来控制声明后的标识符的可见性。Go 语言支持包里公开或者隐藏标识符,让用户能按照自己的规则控制标识符的可见性

  • 当一个标识符的名字以小写字母开头时,这个标识符就是未公开
  • 如果一个标识符以大写字母开头,这个标识符就是公开的,
package counters

type alertCounter int

对于未公开的属性,赋值可以使用类似工厂函数的方式

package counters

type alertCounter int

func New(value int) alertCounter {
 return alertCounter(value)
}

也可以使用 setter 方法

type User struct {
  id int
  name string
}

func (u *User) SetName(name string) {
  u.name = name
}

User 类型被声明为公开的类型。User 类型里声明了两个字段,一个名为 Name 的公开的字段,一个名为 email 的未公开的字段

package entities

// User defines a user in the program.
type User struct {
 Name  string
 email string
}

func main() {
 u := entities.User{
  Name:  "Bill",
  email: "bill@email.com",
 }
 fmt.Printf("User: %v\n", u)
}

试图初始化未公开的字段 email,所以编译器抱怨这是个未知的字段。因为 email 这个标识符未公开,所以它不能在 entities 包外被访问

公开和未公开的内嵌类型是如何赋值的

package entities

// user 在程序里定义一个用户类型
type user struct {
 Name  string
 Email string
}

// Admin 在程序里定义了管理员
type Admin struct {
 user   // 嵌入的类型未公开
 Rights int
}

内嵌类型初始化

func main() {
 // / 创建 entities 包中的 Admin 类型的值
 a := entities.Admin{
  Rights: 10,
 }

 // 设置未公开的内部类型的
 // 公开字段的值
 a.Name = "Bill"
 a.Email = "bill@email.com"

 fmt.Printf("User: %v\n", a)
}

4博文部分内容参考

© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知.


《GO语言实战》


© 2018-2023 liruilonger@gmail.com, All rights reserved. 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。