跟我一起来学golang之《接口》(二)

497 阅读3分钟

这是我参与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

注意,接口对象不能调用接口实现对象的属性