zoukankan      html  css  js  c++  java
  • golang interface接口

    package main
    
    import "fmt"
    
    type Shaper interface {
    	Area() float32
    }
    
    type Square struct {
    	side float32
    }
    
    func (sq *Square) Area() float32 {
    	return sq.side * sq.side
    }
    
    func main() {
    	sq1 := new(Square)
    	sq1.side = 5
    
    	var areaIntf Shaper
    	areaIntf = sq1
    	// shorter,without separate declaration:
    	// areaIntf := Shaper(sq1)
    	// or even:
    	// areaIntf := sq1
    	fmt.Printf("The square has area: %f
    ", areaIntf.Area())
    }
    

      

    上面的程序定义了一个结构体 Square 和一个接口 Shaper,接口有一个方法 Area()

    在 main() 方法中创建了一个 Square 的实例。在主程序外边定义了一个接收者类型是 Square 方法的 Area(),用来计算正方形的面积:结构体 Square 实现了接口 Shaper 。

    所以可以将一个 Square 类型的变量赋值给一个接口类型的变量:areaIntf = sq1 。

    现在接口变量包含一个指向 Square 变量的引用,通过它可以调用 Square 上的方法 Area()。当然也可以直接在 Square 的实例上调用此方法,但是在接口实例上调用此方法更令人兴奋,它使此方法更具有一般性。接口变量里包含了接收者实例的值和指向对应方法表的指针。

    这是 多态 的 Go 版本,多态是面向对象编程中一个广为人知的概念:根据当前的类型选择正确的方法,或者说:同一种类型在不同的实例上似乎表现出不同的行为。

    如果 Square 没有实现 Area() 方法,编译器将会给出清晰的错误信息:

    cannot use sq1 (type *Square) as type Shaper in assignment:
    *Square does not implement Shaper (missing Area method)
    

      如果 Shaper 有另外一个方法 Perimeter(),但是Square 没有实现它,即使没有人在 Square 实例上调用这个方法,编译器也会给出上面同样的错误。

    扩展一下上面的例子,类型 Rectangle 也实现了 Shaper 接口。接着创建一个 Shaper 类型的数组,迭代它的每一个元素并在上面调用 Area() 方法,以此来展示多态行为:

    package main
    
    import "fmt"
    
    type Shaper interface {
    	Area() float32
    }
    
    type Square struct {
    	side float32
    }
    
    func (sq *Square) Area() float32 {
    	return sq.side * sq.side
    }
    
    type Rectangle struct {
    	length, width float32
    }
    
    func (r Rectangle) Area() float32 {
    	return r.length * r.width
    }
    
    func main() {
    
    	r := Rectangle{5, 3} // Area() of Rectangle needs a value
    	q := &Square{5}      // Area() of Square needs a pointer
    	// shapes := []Shaper{Shaper(r), Shaper(q)}
    	// or shorter
    	shapes := []Shaper{r, q}
    	fmt.Println("Looping through shapes for area ...")
    	for n, _ := range shapes {
    		fmt.Println("Shape details: ", shapes[n])
    		fmt.Println("Area of this shape is: ", shapes[n].Area())
    	}
    }
    

      在调用 shapes[n].Area() 这个时,只知道 shapes[n] 是一个 Shaper 对象,最后它摇身一变成为了一个 Square 或 Rectangle 对象,并且表现出了相对应的行为。

    在调用 shapes[n].Area() 这个时,只知道 shapes[n] 是一个 Shaper 对象,最后它摇身一变成为了一个 Square 或 Rectangle 对象,并且表现出了相对应的行为。

    package main
    
    import "fmt"
    
    type stockPosition struct {
    	ticker     string
    	sharePrice float32
    	count      float32
    }
    
    /* method to determine the value of a stock position */
    func (s stockPosition) getValue() float32 {
    	return s.sharePrice * s.count
    }
    
    type car struct {
    	make  string
    	model string
    	price float32
    }
    
    /* method to determine the value of a car */
    func (c car) getValue() float32 {
    	return c.price
    }
    
    /* contract that defines different things that have value */
    type valuable interface {
    	getValue() float32
    }
    
    func showValue(asset valuable) {
    	fmt.Printf("Value of the asset is %f
    ", asset.getValue())
    }
    
    func main() {
    	var o valuable = stockPosition{"GOOG", 577.20, 4}
    	showValue(o)
    	o = car{"BMW", "M3", 66500}
    	showValue(o)
    }
    

      数据类型实现了接口,就能使用以接口变量为参数的方法

    备注:

    有的时候,也会以一种稍微不同的方式来使用接口这个词:从某个类型的角度来看,它的接口指的是:它的所有导出方法,只不过没有显式地为这些导出方法额外定一个接口而已。

  • 相关阅读:
    JavaScript对象模型执行模型
    jQuery+CSS实现的图片滚动效果
    js笔记作用域(执行上下文[execution context],活动对象) 闭包
    JavaScript中的值类型和引用类型
    程序员第一定律:关于技能与收入
    JavaScript 秘密花园 http://bonsaiden.github.com/JavaScriptGarden/zh/
    程序员三大世界观 如何看待HTML5
    10 条建议让你创建更好的 jQuery 插件
    html 打印
    面向对象的 Javascript (声明篇)
  • 原文地址:https://www.cnblogs.com/luffe/p/9742418.html
Copyright © 2011-2022 走看看