zoukankan      html  css  js  c++  java
  • go语言之接口

    Go语言中虽然没有传统面向对象语言中类、集成的概念,不过提供了接口的支持,可以使用接口来使用一些面向对象的特性。

    在 go 语言中,的接口有下面几个特点:

    可以包含0个或多个方法的签名

    只定义方法的签名,不包含实现

    实现接口不需要显式的声明,只需实现相应方法即可

    在 go 中实现接口很简单,不需要显式的声明实现了某个接口,想要实现某个接口,只需要实现接口中的所有方法即可。

    package main

     

    import "fmt"

    import "math"

     

    type Shaper interface {

        Area() float32

        Circumference() float32

    }

     

    type Rect struct {

        Width float32

        Height float32

    }

     

    type Circle struct {

        Radius float32

    }

     

    func (r Rect) Area() int {

        return r.Width * r.Height

    }

     

    func (r Rect) Circumference() int {

        return 2 * (r.Width + r.Height)

    }

     

    func (c Circle) Area() int {

        return math.Pi * c.Radius * c.Radius

    }

     

    func (c Circle) Circumference() int {

        return math.Pi * 2 * c.Radius

    }

     

    func main() {

        r := Rect{10, 20}

        fmt.Printf("Rect w: %f, d: %f, Area: %f, Circumference: %f", r.Width, r.Height, r.Area(), r.Circumference())

     

        c := Circle{5}

        fmt.Printf("Circle r: %f, Area: %f, Circumference: %f", c.Radius, c.Area(), c.Circumference())   

    }

    上面我们定义了一个 Shaper 的接口,其中包含两个方法 Area 和 Circumference,分别用来计算面积和周长。然后我们定义了两个结构体 Rect, Circle 并分别实现了这两个方法。但是上面的程序似乎并没有体现出接口和两个实现类型的关系,下面我们将他们关联起来使用:

     

    func showInfo(s Shaper) {

        fmt.Printf("Area: %f, Circumference: %f", s.Area(), s.Circumference())

    }

     

    注意,这里方法的参数是一个接口类型的,因此我们可以将实现接口的类型的实例传递进去,像下面这样:

     

    r := Rect{10, 20}

    showInfo(r)

     

    c := Circle{5}

    showInfo(c)

     

    在上面的 showInfo 中我们传入了接口类型的对象,如果将实现了接口的类型传递进去,那么会将实际类型的其他特性掩盖住,因此通常我们会想要获取其真正的类型, 可以使用下面的方法:

     

    func showInfo(s Shaper) {

        switch s.(type) {

        case Rect:

            fmt.Println("This is Rect")

        case Circle:

            fmt.Println("This is Circle")       

        }

        fmt.Printf("Area: %f, Circumference: %f ", s.Area(), s.Circumference())

    }

     

    func (a Integer) Less(b Integer) bool{

            return a < b

    }

    func (a *Integer) Add(b Integer){

            *a+=b

    }

    type LessAdder interface{

            Less(b Integer) bool

            Add(b Integer)

    }

    赋值的方式如下:

    func main(){

            var a Integer = 1

            var LA LessAdder = a

            LA.Less(3)

    }

    运行报错:

    cannot use a (type Integer) as type LessAdder in assignment:

            Integer does not implement LessAdder (Add method has pointer receiver)

    这个错误的原因是因为Add方法的类型是指针的形式,由类型指针接收的方法必须由对象指针表示和传入。正确的传递方法应该是var LA LessAdder =&a。这样Add方法就能够满足了。那Less方法传递的是非指针,这个时候是否会报错呢?答案是不会的。原因在于Go语言可以根据下面的函数

    func (a Integer) Less(b Integer) bool{

            return a < b

    }

    自动生成一个新的Less方法

    func (a *Integer) Less(b Integer) bool{

            return (*a) < b

    }

    类型*Integer就既存在Less()方法,也存在Add()方法,满足LessAdder接口。而

    从另一方面来说,根据

    func (a *Integer) Add(b Integer)

    这个函数无法自动生成以下这个成员方法:

    func (a Integer) Add(b Integer) {

    (&a).Add(b)

    }

    因为(&a).Add()改变的只是函数参数a,对外部实际要操作的对象并无影响,这不符合用

    户的预期。所以,Go语言不会自动为其生成该函数。因此,类型Integer只存在Less()方法,

    缺少Add()方法,不满足LessAdder接口.

  • 相关阅读:
    Kostya the Sculptor
    Parade
    zoj 1097 普吕弗序列
    API分析——Jquery UI Dialog
    伸缩性和可用性反模式(转)
    可伸缩性最佳实战(转)
    二叉索引树BIT
    RMQ
    线段树(区间树)
    双栈计算算术表达式
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/13899478.html
Copyright © 2011-2022 走看看