Java程序员学习Go语言入门笔记-index3

15 篇文章 0 订阅
本篇内容:匿名属性、方法、接口

久违的面向对象编程

面向对象编程

面向对象编程离不开继承、封装、多态
go中没有这些概念,它通过其他的方式实现这些特性

继承:匿名属性
封装:方法
多态:接口

匿名属性(匿名字段、匿名组合)

匿名字段可以是自定义结构体类型、内置类型、指针类型

// 匿名属性/字段
package main

import "fmt"

// 自定义结构体User
type User struct {
	id       int // 结构体成员变量,不需要通过var声明,普通变量需要
	no       int
	username string
	password string
}

// Worker
type Worker struct {
	User // 匿名字段,只有结构体类型,没有变量名称,表示Worker继承了User
	int  // 年龄,非结构体匿名字段
	no   int
	dept string
}

func main() {
	// 初始化方式和普通的结构体类型初始化相似
	var worker Worker = Worker{User: User{id: 1, no: 10001, username: "yw"},
		int: 32, no: 30001, dept: "市场部"} // int: 32,非结构体匿名字段-年龄赋值
	fmt.Println("worker =", worker) // worker = {{1 10001 yw } 32 30001 市场部}

	// 访问成员变量
	username := worker.username
	dept := worker.dept
	fmt.Printf("username = %v, dept = %v\n", username, dept) // username = yw, dept = 市场部

	// 重名字段
	workerNo := worker.no
	userNo := worker.User.no                                     // 匿名变量通过User访问,相当于访问父类的属性
	fmt.Printf("workerNo = %v, userNo = %v\n", workerNo, userNo) // workerNo = 30001, userNo = 10001
}

方法

方法比函数在func后面多了一个括号(),声明接收类型,
表示该函数绑定于当前类型,也可以是自定义类型别名,
带有接受者的函数叫做方法

函数更面向过程

方法更面向对象

我们还是来看代码吧

package main

import "fmt"

// 自定义结构体User
type User struct {
	id       int // 结构体成员变量,不需要通过var声明,普通变量需要
	no       int
	username string
	password string
}

// 给User类型添加一个eat方法
func (obj User) eat(food string) { // 这里(obj User)接收的是调用该方法的对象
	fmt.Println(obj.username, "吃", food) // obj是调用者本身
}

func (obj User) changeByValue() {
	obj.username = "hh"
}

func (obj *User) changeByPointer() { // 接受类型可以是显式的指针类型
	(*obj).username = "hh"
	// 或
	// obj.username = "hh" // 因为调用转化的存在:(指针←→变量)
}

type userPointer *User

// func (up userPointer) doSth() {} // 接受类型不可以是隐式的指针类型

func main() {
	var user User = User{id: 1, no: 10001, username: "yw"}
	user.eat("西瓜") // yw eat 西瓜
	user.changeByValue()
	fmt.Println(user) // {1 10001 yw }
	userP := &user
	userP.changeByPointer()
	fmt.Println(user) // {1 10001 hh }
}

在这里插入图片描述

可以存在接受者类型不一样的重名方法,我叫go的方法重载

方法集

类型的方法集:是指可以被该类型的值调用的所有方法的集合
即所有接受者类型为当前类型的方法的集合

继承

匿名字段继承结构体类型时,也继承了父结构体类型的方法集

// 方法继承
package main

import "fmt"

// 自定义结构体User
type User struct {
	id       int // 结构体成员变量,不需要通过var声明,普通变量需要
	no       int
	username string
	password string
}

// Worker
type Worker struct {
	User // 匿名字段,只有结构体类型,没有变量名称,表示Worker继承了User
	int  // 年龄,非结构体匿名字段
	no   int
	dept string
}

func (obj User) eat(food string) { // 这里(obj User)接收的是调用该方法的对象
	fmt.Println("用户", obj.username, "吃", food) // obj是调用者本身
}

// 重名方法
func (obj Worker) eat(food string) { // 这里(obj User)接收的是调用该方法的对象
	fmt.Println("工人", obj.username, "吃", food) // obj是调用者本身
}

func main() {
	// 匿名字段继承结构体类型时,也继承了父结构体类型的方法集
	var worker Worker = Worker{User: User{id: 1, no: 10001, username: "yw"}, int: 32, no: 30001, dept: "市场部"}
	worker.eat("西瓜")      // 重写后的方法 // 就近调用Worker接受者类型方法:工人 yw 吃 西瓜
	worker.User.eat("西瓜") // 调用父结构体eat方法:用户 yw 吃 西瓜
}

方法值和方法表达式

package main

import "fmt"

// 自定义结构体User
type User struct {
	id       int // 结构体成员变量,不需要通过var声明,普通变量需要
	no       int
	username string
	password string
}

// Worker
type Worker struct {
	User // 匿名字段,只有结构体类型,没有变量名称,表示Worker继承了User
	int  // 年龄,非结构体匿名字段
	no   int
	dept string
}

func (obj Worker) doSth() {
	fmt.Println(obj)
}

func main() {
	var worker Worker = Worker{User: User{id: 1, no: 10001, username: "yw"},
		int: 32, no: 30001, dept: "市场部"}

	// 方法值
	doSth1 := worker.doSth // 方法值声明时就传入了调用对象
	doSth1()               // {{1 10001 yw } 32 30001 市场部}

	// 方法表达式
	doSth2 := Worker.doSth // 方法表达式调用时才传入了调用对象
	doSth2(worker)         // {{1 10001 yw } 32 30001 市场部}
}

在这里插入图片描述

接口

type 接口名称 interface {}

结构体绑定有接口的实现方法,接口就可以实例化为该结构体,并调用方法
接口可以继承

package main

import "fmt"

// 自定义接口Animal
type Animal interface {
	doSth()
}

// 自定义接口Animal
type Bird interface {
	Animal // 通过匿名字段,继承接口Animal
}

// 自定义结构体Parrot鹦鹉
type Parrot struct {
	id       int
	name     string
	language string
}

// 自定义结构体User
type User struct {
	id       int
	no       int
	username string
	password string
}

func (obj User) doSth() {
	fmt.Println("用户信息:", obj)
}

func (obj Parrot) doSth() {
	fmt.Println("鹦鹉信息:", obj)
}

func main() {
	var animal Animal

	var user User = User{id: 1, no: 10001, username: "yw"}
	// 结构体绑定有接口的实现方法,接口就可以实例化为该结构体,并调用方法
	animal = user
	animal.doSth() // 用户信息: {1 10001 yw }

	// 多态
	var parrot Parrot = Parrot{id: 3, name: "Polly", language: "英语"}
	animal = parrot
	animal.doSth() // 鹦鹉信息: {3 Polly 英语}
}

在这里插入图片描述

空接口

interface{}
空接口可以接受任何变量,所有类型都继承空接口
类似Java中的Object类型

类型断言

data, ok := obj.(type)
判断obj是否属于type类型,返回数据和true或false

// 空接口
var obj interface{} = "abc"

// 接口断言:data, ok := obj.(type),判断obj是否属于type类型,返回数据和true或false
intData, intOk := obj.(int)
fmt.Println(intData, intOk) // 0 false
stringData, stringOk := obj.(string)
fmt.Println(stringData, stringOk) // abc true

在这里插入图片描述

不当之处,请予指正。

上一篇:Java程序员学习Go语言入门笔记-index2
下一篇:Java程序员学习Go语言入门笔记-index4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值