Golang06-go语言interface接口

151 阅读4分钟

interface接口

接口的概念,接口用于定义对象的行为。实现这种行为(方法或者函数)的细节由对来来决定。

在Go语言中,接口时一组方法签名,接口指定了类型应该具有的方法,类型决定了如何实现这些方法。

Go语言的类型都是隐式实现接口的。任何定义了接口中所有方法的类型都被称为隐式地实现了该接口

package main

import "fmt"

type phone interface {
	call()
}

type Iphone struct {

}
type Huawei struct {

}

func (huawei Huawei)call()  {
	fmt.Println("我用的华为")
}
func (apple Iphone)call()  {
	fmt.Println("我用的苹果")
}

func main()  {
	//定义接口变量
	var phone1 phone
	phone1=new(Huawei)
	fmt.Printf("%T,%v,%p\n",phone1,phone1,&phone1)
	phone1.call()
	phone1=Huawei{}
	fmt.Printf("%T,%v,%p\n",phone1,phone1,&phone1)
	phone1.call()
	phone1=new(Iphone)
	fmt.Printf("%T,%v,%p\n",phone1,phone1,&phone1)
	phone1.call()
	phone1=Iphone{}
	fmt.Printf("%T,%v,%p\n",phone1,phone1,&phone1)
	phone1.call()
}
/*
*main.Huawei,&{},0xc000038240
我用的华为
main.Huawei,{},0xc000038240
我用的华为
*main.Iphone,&{},0xc000038240
我用的苹果
main.Iphone,{},0xc000038240
我用的苹果

Process finished with the exit code 0

*/

大黄鸭duck typing

go没有implements或extends关键字,这类编程语言叫做duck typing编程语言

1、大黄鸭不是鸭子,没有生命
2、duck typing

duck typing是描述事物的外部行为而非内部结构。“一只鸟走起来像鸭子,叫起开像鸭子,那么这只鸟可以被称为鸭子。”

3、duck typing编程语言

使用duck typing 的编程语言往往被归类为“动态类型语言。”或者“解释型语言”,如python,JavaScript,ruby。而duck typing 编程语言被归为"静态类型语言".C/C++ 、Java

4、非duck typing编程语言

以Java为例,一个类必须显式声明"类实现了某个接口",然后才能用在这个接口可以使用的地方。如果有一个第三方Java库,这个库中的某个类没有声明它实现了某个接口。那么即使这个类真的有哪些接口中的方法,也不能把这个类用在那些需要用到接口的地方。但在duck typing编程语言中就可以这样做,因为它不要求一个类显示声明它实现了某个接口

5、动态类型语言的有缺点

动态类型语言有很多好处,python写起来很快。但是缺陷是需要运行时才发现,相反,静态类型语言往往编译时就发现这类错误:如果某个变量的类型没有显示地声明实现了某个接口。那么,这个变量就不能用在一个要求实现这个接口的地方。

第一、结构体类型T不需要显示地声明它实现了接口I,只要类型T实现了接口I规定地所有方法,它就自动地实现了接口I,这样动态类型语言一样省了很多代码,少了许多限制。

第二、将结构体类型的变量显式或者隐式地转换为接口I类型的变量i。这样就可以和其他静态类型语言一样,在编译时检查参数的合法性。

duck Typing Sample

package main

import "fmt"

type ISayHello interface {
	SayHello() string
}

type duck struct {
	name string
}

type persons struct {
	name string
}
//这里就是duck typing的具体表现
func (d duck)SayHello() string  {
	return d.name+"叫:gagaga!"
}
//这里就是duck typing的具体表现
func (p persons)SayHello() string {
	return p.name+"说:Hello!"
}

func main()  {
	//定义实现接口地对象
	duck:=duck{"小黄鸭"}
	person:=persons{"JackMa"}
	fmt.Println(duck.SayHello())
	fmt.Println(person.SayHello())
	fmt.Println("------------------------")
	//定义接口类型的变量
	var i ISayHello
	i=duck
	fmt.Printf("%T,%v,%p\n",i,i,&i)
	fmt.Println(i.SayHello())
	i=person
	fmt.Printf("%T,%v,%p\n",i,i,&i)
	fmt.Println(i.SayHello())
}

/*
小黄鸭叫:gagaga!
JackMa说:Hello!
------------------------
main.duck,{小黄鸭},0xc000038260
小黄鸭叫:gagaga!
main.persons,{JackMa},0xc000038260
JackMa说:Hello!

Process finished with the exit code 0

*/


怎么说呢,Duck Typing就是将对象的方法和其继承的类进行了解偶,程序判断一个对象是声明并不是通过它的数据类型定义来判断的,而是判断它是否满足了某些特定的方法和属性定义,以此加大了编程的灵活度 —— 虽然我不继承自某个类,但我依然可以完成某些工作(实现某些函数和方法)

多态

如果有几个相似而不完全相同的对象,有时人们要求在向它们发出同一个消息时,它们的反应各不相同,分别执行不同的操作

空接口

空接口就是没有任何方法。任意类型都可以实现该接口。空接口这样定义:

interface{}

接口对象转换

package main

import (
	"fmt"
	"math"
)

//定义接口
type shape interface {
	perimeter() float64
	area() float64
}

type rectangles struct {
	a,b float64
}

type triangles struct {
	a,b,c float64
}

type circles struct {
	radius float64
}

//定义实现接口方法

func (r rectangles) perimeter() float64 {
	return (r.a+r.b)*2
}
func (r rectangles) area() float64 {
	return r.a*r.b
}

func (t triangles) perimeter() float64  {
	return t.a+t.b+t.c
}

//三角形知道三边求面积,根据海伦公式
func (t triangles) area() float64  {
	p:=(t.a+t.b+t.c)/2
	ret:=math.Sqrt(math.Abs(p*(p-t.a)*(p-t.b)*(p-t.c)))
	return ret
}
func (c circles ) perimeter() float64 {
	return math.Pi*c.radius*2
}
func (c circles) area() float64{
	return math.Pi*c.radius*c.radius
}

func main()  {
	r1:=rectangles{3,4}
	t1:=triangles{3,4,5}
	c1:=circles{10}
	fmt.Println(r1.perimeter())    //14
	fmt.Println(r1.area())         //12
	fmt.Println(t1.perimeter())    //12
	fmt.Println(t1.area())         //6
	fmt.Println(c1.perimeter())    //62.83185307179586
	fmt.Println(c1.area())         //314.1592653589793
}