go语言修炼之五

面向对象基础-接口

我们继续golang面向对象设计的必要知识:接口

说明

在go语言里,接口是一种类型,用type描述,指定类型为interface,里面只包含该接口的方法,不包含变量。

type UserReader interface {
	Read() string
	Write(string) string
	ShowMe()
}

这里对比下我们之前学习的结构体类型和接口类型。(因为接口也是一种类型,同type struct一样,所以type interface在应用时也存在需要实例化或者赋值给一个明确的变量的步骤,后面会看到例子。)

type xxx struct{
	....
}
type yyy interface{
	...
}

上面一个是定义了叫xxx的结构体,一个是定义了叫yyy 的接口,是两种类型。

我们在mylib包的user.go文件里继续工作…

package mylib

import (
	"fmt"
)

type MyUser struct {
	Id            int
	Name          string
	UserGroup     string
	CashBanlance  float32
	OtherBanlance float32
	IfDel         bool
	ModifyTime    string
}

type UserControl interface {
	Read() string
	Write(string) string
}

//实现MyUser类的方法
func (e MyUser) ShowMe() {
	fmt.Println("id=", e.Id)
	fmt.Println("name=", e.Name)
	fmt.Println("group=", e.UserGroup)
	fmt.Println("cash=", e.CashBanlance)
	fmt.Println("other=", e.OtherBanlance)
	fmt.Println("time=", e.ModifyTime)
}

//用MyUser类去实现我们设计的接口,使MyUser类能够提供该接口
func (e MyUser) Read() string {
	return "my name is " + e.Name
}

func (e MyUser) Write(str string) string {
	e.Name = str
	return "my name now is" + e.Name
}

在上面,我们继续使用了myuser类(他包含一个结构体,一个showme方法),同时我们增加一个用户读写接口。并在myuser类上实现该接口。也就是最后两个函数,
func (e Myuser) Read() string{…}
func (e MyUser) Write(str string) string{…}
这里需要注意的是,UserControl接口定义了两个方法,要实现该接口,就必须完整实现他包含的所有方法,这里就是需要你实现两个方法,一个write一个read。只要实现了接口定义的所有方法,你就实现了该接口。另外一点,一个接口可以不包含方法,这个接口就是空接口,即interface{}

接口应用

接口定义好了,如何使用?
最简单的用法,跟类一样,实例化之后即可使用,本例即为

package main

import (
	"fmt"
	"mylib"
)

func main() {

	user1 := mylib.MyUser{
		1,
		"wen",
		"A2",
		15.93,
		16.88,
		true,
		"2020-05-01 14:55:32",
	}

	//定义一个接口
	var userc mylib.UserControl
	//接口赋值
	userc = user1
	fmt.Println(userc.Read())
}

执行结果如下
在这里插入图片描述

因为user1对应的类MyUser已经实现了接口UserControl所要求的所有方法,一个write,一个read,所以MyUser类的实例可以直接赋值给接口UserControl的实例。也就是这里的userc=user1,然后就可以通过userc调用接口里规定的方法了。
(这种接口实现方式,叫做隐式接口,是GO语言特点之一,有别于java这样的传统面向对象语言,java中接口需要显式的声明。)

我们再来看看该接口的另外一个方法,write。测试代码如下:

package main

import (
	"fmt"
	"mylib"
)

func main() {

	user1 := mylib.MyUser{
		1,
		"wen",
		"A2",
		15.93,
		16.88,
		true,
		"2020-05-01 14:55:32",
	}

	var userc mylib.UserControl

	userc = user1
	fmt.Println(userc.Read())
	//上面是两部并一步,先执行userc.Read()方法,再调用fmt的print模块打印
	//该方法return的值。

	//调用该接口的方法,变更新名字
	userc.Write("newname")
	fmt.Println(userc.Read())

}

输出的结果是:
输出结果
跟设想的不一样?本意是通过接口提供的方法变更数据对应的值,但仍然输出原名称。

这里涉及到GO语言参数传值方式。简单来讲,go语言参数传递,默认是值拷贝的方式,也就是在实现接口时
func (e Myuser) Read() string{…}
func (e MyUser) Write(str string) string{…}
两个方法,都复制了一份实际传参时的拷贝数据在方法内部(局部空间内)无法影响到参数对应数据本身。

因此我们用指针方式来实现接口构造,目的是为了接口接受实例化或者初始化后,接口的方法是直接影响给予这个接口赋值的原始对象的。
func (e *Myuser) Read() string{…}
func (e *MyUser) Write(str string) string{…}
用 * 号表示,采用对象的指针来传值,也就是方法直接作用到初始数据对象。
在接口初始化时,使用userc = &user1 形式,将struct user1 的指针赋值给userc,
这样userc和user1实际指向了内存中同一个数据对象块。
调整后的代码和效果如下:

user.go

package mylib

import (
	"fmt"
)

type MyUser struct {
	Id            int
	Name          string
	UserGroup     string
	CashBanlance  float32
	OtherBanlance float32
	IfDel         bool
	ModifyTime    string
}

type UserControl interface {
	Read() string
	Write(string) string
	ShowMe()
}

func (e MyUser) ShowMe() {
	fmt.Println("id=", e.Id)
	fmt.Println("name=", e.Name)
	fmt.Println("group=", e.UserGroup)
	fmt.Println("cash=", e.CashBanlance)
	fmt.Println("other=", e.OtherBanlance)
	fmt.Println("time=", e.ModifyTime)
}
func (e *MyUser) Read() string {
	return "my name is " + e.Name
}

func (e *MyUser) Write(str string) string {
	e.Name = str
	return "my name now is " + e.Name
}

mymain.go

package main

import (
	"fmt"
	"mylib"
)

func main() {

	user1 := mylib.MyUser{
		1,
		"wen",
		"A2",
		15.93,
		16.88,
		true,
		"2020-05-01 14:55:32",
	}

	var userc mylib.UserControl

	userc = &user1
	fmt.Println(userc.Read())

	fmt.Println(userc.Write("newname"))
	userc.Read()
	user1.ShowMe()

}

输出结果:
在这里插入图片描述
可以看到,userc.Read()和user1.ShowMe()都显示出,user1内的Name发生了实际的变化。

尾声

这部分后面的内容,如果之前学习使用过指针有所了解,会好一点。go设计者有以前设计C语言编译器的,所以沿用了一部分C的设计思想。

吾听风雨
吾览江山
常觉风雨江山外
有万不得已者在

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值