Golang学习笔记 方法和接口
来源:互联网 发布:分水岭分割算法流程图 编辑:程序博客网 时间:2024/06/11 15:00
在编程语言中,方法和函数的概念需要搞清楚。函数指的是一个封装的代码块,我们可以直接调用它,并返回结果。而方法其实也是一种函数,只不过方法需要和某个对象绑定。Golang并没有类的概念,不过仍然有方法和接口这些概念。
方法
方法接收者
方法接收者是一个特殊参数,给函数指定了这个参数之后,函数就成为方法了。这个特性有点像Kotlin和C#中的扩展方法,定义了带有接收者的方法之后,接收者这个类型就好像定义了这个方法一样,我们可以直接在该类型上调用方法。这在功能上,和面向对象的概念是很类似的。
例如下面这样,定义了一个汽车结构,然后定义了一个接受者方法。然后就可以用面向对象的方式来调用这个方法了。
func Method() { //方法接收者 car := Car{id: 1} car.beep()}type Car struct { id int}func (car Car) beep() { fmt.Printf("Car %v beeps", car.id)}
接收者方法也有一些限制,这也是它和扩展方法之间的区别。接收者方法的接受者类型,必须和接收者方法定义在同一个包中。所以很多非自定义的类型,以及基本类型都不能当做接收者的类型。当然也可以投机取巧,在自己的包中重新为这些类型取个名字即可。
//把基本类型重新定义一下,就可以当做接收者类型了type MyString stringfunc (str MyString) hello() { fmt.Println("hello" + str)}
指针接收者
接收者的类型可以是指针,如果希望在接收者方法中修改接收者的属性,就需要指针类型了。下面的代码对Car
结构体添加了两个方法,第一个由于没有指针类型,所以不会修改原始结构体中的值;而第二个方法会修改汽车的id。
func (car Car) beep() { fmt.Printf("Car %v beeps", car.id)}func (car Car) changeId() { car.id += 1}func (car *Car) changeRealId() { car.id += 1}
接口
听起来很奇怪,如果Golang没有类型,为什么会有接口的概念?让我们来看看Golang如何解决这些问题。
定义接口
在Golang中,接口就是一组方法签名的集合。下面就定义了一个接口。
type ICar interface { beep() drive(driver string)}
实现接口
在Golang中,其实并没有“实现接口”这一说法。在Golang中接口是隐式实现的,也就是说我们不需要implements
这些关键字。只要一个类型的接收者方法和接口中定义的方法一致,Golang就认为这个类型实现了该接口。下面是一个简单的例子。
func Interface() { car := MyCar{id: 1} var icar ICar = car icar.beep() icar.drive("yitian")}type ICar interface { beep() drive(driver string)}type MyCar struct { id int}func (car MyCar) beep() { fmt.Printf("car %v beeps\n", car.id)}func (car MyCar) drive(driver string) { fmt.Printf("%v drives car %v\n", driver, car.id)}
空接口
什么方法都没定义的接口就是空接口。根据Golang的概念,空接口被任何类型隐式实现,所以空接口可以容纳任何类型。
//空接口可以作为任何类型使用type Everything interface {}var e Everything = "123"fmt.Println(e)
类型细化
定义和实现接口是一个类型泛化的过程,在这个过程中,我们抹消掉了类型特有的部分,让类型公有的部分能够统一利用。不过有时候需要反过来,将一个接口对象转换为原始的具体类,让我们能够获取更具体的行为。
现在来看看在Golang中,这件事情应该怎么做。再次使用上面定义的类型。可以看到和C系语言的括号强转方式不同,在Golang中是.(T)
类型的语法。
//特化类型myCar := icar.(MyCar)//myCar是MyCar类型变量myCar.beep()
这个语法还有一个携带一个成功标志的版本 t, ok := i.(T)
。当成功标志为真时,表示成功将接口转换为具体类型,否则表示该接口不是具体类型的实例。
如果要进行多次判断,可以利用switch
语句。下面是一个例子。
func testType(i interface{}) { switch i.(type) { case string: fmt.Printf("%v is string\n", i) case int: fmt.Printf("%v is int\n", i) default: fmt.Printf("%v is interface{}\n", i) }}
对这个方法调用多次,可以看到针对不同的类型,方法会返回不同结果。
//类型检测testType("abc")testType(123)testType(nil)
- Golang学习笔记 方法和接口
- Golang 学习笔记 ---类型和一个 HelloWorld
- Golang学习笔记 包和项目构成
- Golang学习笔记 数据类型和变量
- Golang学习笔记 结构体和指针
- golang new和make学习笔记
- golang 组合和接口
- golang语法学习(三) golang的面向对象机制-接口与方法
- golang语法学习(三) golang的面向对象机制-接口与方法
- 黑马程序员-抽象方法和接口-学习笔记
- GoLang学习基础笔记
- Golang学习笔记//序
- Golang Log 学习笔记
- Golang学习笔记:常见问题
- Golang学习笔记
- golang学习笔记
- golang学习笔记
- golang学习笔记
- js 冒泡排序
- React Native移动开发实战-1-React Native的JSX解决方案
- 用模板实现顺序表和带头结点的双向循环链表
- 粘贴版
- 杭电1232畅通工程(最小生成树模板)
- Golang学习笔记 方法和接口
- javascript常用对象
- 归并排序
- hdu2816 I LVOE YOU TOO
- 关于头结点的一些知识!
- HDU1863(畅通工程)
- 关于IDEA-maven环境下如何使用log4j
- 17 多校 3
- CT之cnn