ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

接口

2021-12-11 18:34:26  阅读:114  来源: 互联网

标签:定义 Dog 接口 type eat Name


十六、接口

1 定义接口

在面向对象中,接口规范了一个对象的行为,接口指定对象必须实现的方法,而实现的细节由对象自己去完成。go语言中同样提供接口,它把所有的具有共性的方法定义在一起,只要任何其他类型只要实现了这些方法就是实现了这个接口。

接口的定义语法如下:

type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

接口是方法的集合,要实现这个接口就必须实现这些方法。示例:

// 定义接口
type Animal interface {
	sleep()
	eat()
}

// 定义结构体
type Dog struct {
	Name string
	Age  int
}

// 为Dog绑定方法实现接口
func (dog Dog) sleep() {
	fmt.Println(dog.Name + "is sleeping!")
}

//为Dog绑定方法实现接口
func (dog Dog) eat() {
	fmt.Println(dog.Name + "is eating!")
}

func main() {
	d := Dog{
		Name: "小狗",
		Age:  5,
	}
	d.eat()
	d.sleep()
}

上面定义了一个Animal接口,要求实现两个方法。然后定义一个Dog结构体,为它绑定这两个方法,go与java不同,不需要显式声明实现的接口,只要这个类型实现了接口的所有方法,就默认实现了这个接口。但是,这样定义与之前为结构体绑定方法没有区别,把接口去掉程序仍然可以正常工作。

2 接口的作用

接口的实际应用是实现多态。接口是一种数据类型,所以我们可以定义接口类型的变量,然后将其它实现接口的结构赋值给它,实现多态。

示例:

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

// 定义结构体
type Dog struct {
	Name string
	Age  int
}
type Bird struct {
	Name string
}

//为Dog绑定方法实现接口
func (dog Dog) eat() {
	fmt.Println(dog.Name + "只吃肉")
}

//为Bird绑定方法实现接口
func (bird Bird) eat() {
	fmt.Println(bird.Name + "吃虫子")
}

func main() {
	// 定义nil接口
	var animal Animal
	
	animal = Bird{Name: "麻雀"}
	animal.eat() //麻雀吃虫子

	animal = Dog{Name: "小狗"}
	animal.eat() //小狗只吃肉

}

接口是动态的,就像切片是对数组的动态引用一样,接口也是类似的工作方式。

上面的程序中,我们定义了Animal接口,且BirdDog都实现了这个接口,然后我们在main函数中,先定义一个未赋值的接口。首先将Bird指定给它,此时animal的动态类型就是Bird,此时访问animal接口时,只会返回动态值的类型(eat方法),它的静态类型(Name字段)保持隐藏。然后,我们将Dog指定给它,此时的动态类型就是Dog,我们访问的eat方法就是绑定给Dog的方法,由此实现了多态。

3 类型断言

先介绍类型断言的语法:

value, ok := i.(Type)

上节提到接口不能访问低层的静态字段,我们可以使用类型断言来获取这些基础值。

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

// 定义结构体
type Dog struct {
	Name string
	Age  int
}
type Bird struct {
	Name string
}

//为Dog绑定方法实现接口
func (dog Dog) eat() {
	fmt.Println(dog.Name + "只吃肉")
}

//为Bird绑定方法实现接口
func (bird Bird) eat() {
	fmt.Println(bird.Name + "吃虫子")
}

func main() {
	// 定义接口
	var animal Animal
	animal = Dog{Name: "小狗", Age: 5}
	// 类型断言,判断animal的具体类型是否为Dog
	value, ok := animal.(Dog)
	fmt.Println(ok)
    // 断言成功,获取底层字段内容
	fmt.Println(value.Age)
	fmt.Println(value.Name)

}

其中,类型断言如果正确,就将此时的底层值赋值给animal,将true赋值给ok;反之,animal为该类型的零值,ok=false

4 多接口

一个类型可以实现多个接口。例:

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

type Habit interface {
	football()
}

// 定义结构体
type Dog struct {
	Name string
}

// 实现Animal接口
func (dog Dog) eat() {
	fmt.Println(dog.Name + "只吃肉")
}
// 实现Habit接口
func (dog Dog) football() {
	fmt.Println(dog.Name + "爱玩足球")
}

上面例子中,Dog实现了两个接口,也就意味着可以将Dog类型的值赋给AnimalHabit接口类型的变量。

5 空接口

当接口没有方法时,它被称为空接口。 除了有名的空接口,还可以定义匿名的。

匿名空接口的定义为 interface{},一般用于函数的形式参数。空接口不规范任何方法,也就意味着所有类型都实现了空接口。举例说明:

type str string

// 函数接收一个空接口
func foo(in interface{}) {
	fmt.Println(in)
}

func main() {
	s := str("hello world")
	i := 5
	foo(s)
	foo(i)
}

我们自定义一个str类型,还有一个int类型的数据,将它传递给foo,由于任何类型都实现空接口,空接口作为函数的参数可以保存任何类型的值,所以这个函数可以接收所有类型的数据。

6 接口嵌套

顾名思义,举例

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

type Habit interface {
	football()
}
type Dog interface {
	sleep()
	Animal
	Habit
}

定义的Dog接口里,包含AnimalHabit,所以要实现Dog必须实现这些接口(类似于面向对象的继承)

标签:定义,Dog,接口,type,eat,Name
来源: https://www.cnblogs.com/yyyzyyyz/p/15676651.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有