这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战
承接上篇文章继续学习接口相关知识。
嵌入interface
package main
import "fmt"
type Human interface {
Len()
}
type Student interface {
Human
}
type Test struct {
}
func (h *Test) Len() {
fmt.Println("成功")
}
func main() {
var s Student
s = new(Test)
s.Len()
}
运行结果:
成功
示例代码:
package test
import (
"fmt"
)
type Controller struct {
M int32
}
type Something interface {
Get()
Post()
}
func (c *Controller) Get() {
fmt.Print("GET")
}
func (c *Controller) Post() {
fmt.Print("POST")
}
package main
import (
"fmt"
"test"
)
type T struct {
test.Controller
}
func (t *T) Get() {
//new(test.Controller).Get()
fmt.Print("T")
}
func (t *T) Post() {
fmt.Print("T")
}
func main() {
var something test.Something
something = new(T)
var t T
t.M = 1
// t.Controller.M = 1
something.Get()
}
运行结果:
T
Controller实现了所有的Something接口方法,当结构体T中调用Controller结构体的时候,T就相当于Java中的继承,T继承了Controller,因此,T可以不用重写所有的Something接口中的方法,因为父构造器已经实现了接口。
如果Controller没有实现Something接口方法,则T要调用Something中方法,就要实现其所有方法。
如果something = new(test.Controller)则调用的是Controller中的Get方法。
T可以使用Controller结构体中定义的变量
空接口
使用空接口,可以实现各种类型的对象存储。
使用空接口,接收任意类型作为参数。
package main
import "fmt"
type Dog struct {
age int
}
type Cat struct{
weigh float64
}
type Animal1 interface {
}
//使用空接口,接收任意类型作为参数
func info(v interface{}) {
fmt.Println(v)
}
func main() {
/*
使用空接口,可以实现各种类型的对象存储。
*/
d1:= Dog{1}
d2 := Dog{2}
c1 :=Cat{3.2}
c2:=Cat{3.5}
animals:=[4] Animal1{d1,d2,c1,c2}
fmt.Println(animals)
info(d1)
info(c1)
info("aaa")
info(100)
var i Animal1
i = d1
switch m:=i.(type) {
case Dog:
fmt.Println(m.age)
case Cat:
fmt.Println(m.weigh)
}
}
判断接口的实际类型
方法一:
a可能是任意类型
a.(某个类型) 返回两个值 inst 和 ok ,ok代表是否是这个类型,Ok如果是 inst 就是转换后的类型。
方法二:
a.(type) type是关键字 结合switch case使用
TypeA(a) 是强制转换。
示例代码:
package main
import (
"math"
"fmt"
)
type Shape interface {
area() float64
peri() float64
}
type Triangle struct {
a float64
b float64
c float64
}
func (t Triangle) peri() float64 {
return t.a + t.b + t.c
}
func (t Triangle) area() float64 {
p := t.peri() / 2
area := math.Sqrt(p * (p - t.a) * (p - t.b) * (p - t.c))
return area
}
type Circle struct {
r float64
}
func (c Circle) peri() float64 {
return 2 * math.Pi * c.r
}
func (c Circle) area() float64 {
return math.Pi * c.r * c.r
}
//测试函数
func testArea(s Shape){ //s = t
fmt.Println("面积:",s.area())
}
func testPeri(s Shape){
fmt.Printf("周长:%.2f\n",s.peri())
}
//判断类型
func getType(s Shape){
/*
a可能是任意类型
a.(某个类型) 返回两个值 inst 和 ok ,ok代表是否是这个类型,Ok如果是 inst 就是转换后的类型。
*/
if inst,ok := s.(Triangle);ok{
fmt.Println("是Triangle类型。。三边是:",inst.a,inst.b,inst.c)
}else if inst,ok:=s.(Circle);ok{
fmt.Println("是Circle类型,半径是:",inst.r)
}else{
fmt.Println("以上都不对。。")
}
}
//
func getType2(s Shape){
/*
a.(type) type是关键字 结合switch case使用
TypeA(a) 是强制转换
*/
switch inst:=s.(type) {
case Triangle:
fmt.Println("三角形啊。。",inst.a,inst.b,inst.c)
case Circle:
fmt.Println("圆形啊。。",inst.r)
}
}
func main() {
t := Triangle{3,4,5}
testArea(t)
c := Circle{2.5}
testPeri(c)
//定义一个接口类型的数组:Shape类型,可以存储该接口的任意实现类的对象作为数据。
var arr[4] Shape
arr[0] = t
arr[1] = c
arr[2] = Triangle{1,2,3}
arr[3] = Circle{5}
//判断类型
getType(t)
getType2(c)
}
运行结果:
面积: 6
周长:15.71
是Triangle类型。。三边是: 3 4 5
圆形啊。。 2.5
注意,接口对象不能调用接口实现对象的属性