zoukankan      html  css  js  c++  java
  • golang学习笔记 ----interface(接口3)

    Go的接口

        Go的接口定义了一组方法(方法集),但不包含这些方法的具体实现。接口提供了一种方式来说明某类对象具有的行为,它的主要特点如下:

    • 接口实际上就是一组方法声明的集合,没有具体实现,没有字段属性
    • 某个类型只要实现了某个接口的所有方法,就实现了该接口,不需要显示声明实现了什么接口
    • 接口可以嵌入其它的接口

    接口的定义和使用

        定义接口的形式:

    type InterfaceName interface {
       Method1(param_list) return_type
       Method2(param_list) return_type
    }

        下面是一个接口使用的实例,定义了一个Shaper的接口,它包含了Area()Perimeter两个方法;再定义了一个Square类型,它实现了上述具体两个方法,从而继承了接口。在主程序中,就可以创建一个Square类型的变量赋值给接口Shaper

    //定义接口
    type Shaper interface {
        Area() float64
        Perimeter() float64
    }
    //定义类型正方形
    type Square struct {
        side float64
    }
    //实现接口中的方法Area
    func (sq Square) Area() float64 {
        return sq.side * sq.side
    }
    //实现接口中的方法Perimeter
    func (sq Square) Perimeter() float64 {
        return sq.side * 4
    }
    func main() {
        var sq Shaper
        sq = Square{
            side: 2,
        }
        fmt.Println(sq.Area())
    }

    要注意的是,当对象赋值给接口时(sq=Square{side:2,}),会对对象进行拷贝,再赋值给接口,接口中保存的是指向这个拷贝的地址指针。为了性能考虑,我们也可以将对象的指针赋值给接口,这样就不需要拷贝整个原始对象,只拷贝对象地址,地址还是指向原来的对象。上面的代码可以改成:

    //定义接口
    type Shaper interface {
        Area() float64
        Perimeter() float64
    }
    //定义类型正方形
    type Square struct {
        side float64
    }
    //实现接口中的方法Area
    func (sq *Square) Area() float64 {
        return sq.side * sq.side
    }
    //实现接口中的方法Perimeter
    func (sq *Square) Perimeter() float64 {
        return sq.side * 4
    }
    func main() {
        var sq Shaper
        sq = &Square{
            side: 2,
        }
    }

    此外,还需要注意到几点:

    • 多个类型可以实现同一个接口
    • 实现某个接口的类型除了实现接口要求实现的方法外,还可以有其它的方法
    • 一个类型可以实现多个接口

    在接口中内嵌接口

        在Go接口的声明中同样可以嵌入一个接口,实现该外层接口的类型同样需要实现内嵌接口声明的方法

    package main
    
    import (
        "fmt"
    )
    
    //定义类型正方形
    type Square struct {
        side float64
    }
    
    type Shaper interface {
        Area() float64
        Perimeter() float64
        infoPrint //嵌入接口
    }
    type infoPrint interface {
        PrintInfo()
    }
    
    //计算面积
    func (sq Square) Area() float64 {
        return sq.side * sq.side
    }
    
    //计算周长
    func (sq Square) Perimeter() float64 {
        return sq.side * 4
    }
    
    //实现内嵌接口的方法
    func (sq Square) PrintInfo() {
        fmt.Println("我是一个正方形")
    }
    func main() {
        var sq Shaper
        sq = Square{
            side: 2,
        }
        sq.PrintInfo()
    }

    接口转换

        不同的接口之间可以进行转换,转换的原则是大接口转小接口,即将拥有内嵌子接口的接口转换为内嵌子接口

    type Shaper interface {
        Area() float64
        Perimeter() float64
        infoPrint          //嵌入接口
    }
    type infoPrint interface {
        PrintInfo()
    }
    //省略方法实现
    func main(){
       var sq Shaper
       sq = Square{
       side: 2,
     }
     var ip infoPrint
       ip = infoPrint(sq)  //这里将Shaper转换为inforPrint
       ip.PrintInfo()
    }
    

      

    空接口

        如果一个接口中不含任何的方法,那么该接口是个空接口,所有的类型都实现了空接口,它相当于所有类型的基类,类似于Java中的Object

    type Empty interface {}

        可以给一个空接口的变量赋值任何类型

    类型断言

        一个接口类型的变量中可能包含着不同实际类型的值(实现接口的可以有不同的类型),当我们需要判断接口变量中的实际类型时,可以使用类型断言来检测     假设i是一个接口变量,T是某个具体实现该接口的类型,那么可以使用下面的语句来检测i是否为类型T

    s, ok := i.(T)

        当接口变量i的实际类型是T时,si转换到类型T的值,ok的值是true;当接口变量i的实际类型不是T时,s是类型T的零值,okfalse。下面是一段检测接口类型的实例:

    package main
    
    import (
        "fmt"
    )
    
    type Shaper interface {
        Area() float64
        Perimeter() float64
    }
    type Square struct {
        side float64
    }
    
    //计算面积
    func (sq Square) Area() float64 {
        return sq.side * sq.side
    }
    
    //计算周长
    func (sq Square) Perimeter() float64 {
        return sq.side * 4
    }
    func main() {
        sq := Square{
            side: 2,
        }
        isShape(sq)
    }
    
    //判断接口中的数据类型
    func isShape(s Shaper) {
        if sp, ok := s.(Square); ok {
            fmt.Println(sp, "is a shaper")
        } else {
            fmt.Println("none")
        }
    }

    接口变量的类型也可以用一种type-switch的形式去检测:

    package main
    
    import (
        "fmt"
    )
    
    type Shaper interface {
        Area() float64
        Perimeter() float64
    }
    type Square struct {
        side float64
    }
    
    func (sq Square) Area() float64 {
        return sq.side * sq.side
    }
    func (sq Square) Perimeter() float64 {
        return sq.side * 4
    }
    func main() {
        sq := Square{
            side: 2,
        }
        whatType(sq)
    }
    func whatType(s interface{}) {
        switch v := s.(type) {
        case Square:
            fmt.Println(v, "is a square")
        case int:
            fmt.Println(v, "is a square")
        default:
            fmt.Println("none")
        }
    }

    在函数whatType中,对接口变量的类型进行检测,函数传入的是一个空接口类型的参数,v = s.(type)得到变量s的具体类型,然后对case中列举的类型进行匹配,如果被检测的类型没有在case语句列举的类型中,就会执行default语句。但注意type-switch中不允许使用fallthrough

  • 相关阅读:
    openlayers方法总结
    AJAX 数据库实例
    AJAX 请求服务器
    得到XMLHttpRequest对象
    AJAX 简介
    AJAX 服务器端的脚本
    HTTP GET 最多发送100个字符
    AJAX XMLHttpRequest 对象
    Dictionary、ArrayList、Hashtable和数组 Array 的区别
    AJAX 请求实例
  • 原文地址:https://www.cnblogs.com/saryli/p/13359234.html
Copyright © 2011-2022 走看看