• go学习笔记-面向对象(Methods, Interfaces)


    面向对象(Methods, Interfaces)

    Method

    method是附属在一个给定的类型上的,他的语法和函数的声明语法几乎一样,只是在func后面增加了一个receiver(也就是method所依从的主体)。

    语法

    func (r ReceiverType) funcName(parameters) (results)
    

    示例

    type rectangle struct {
    	width  float64
    	heigth float64
    }
    
    func (receiver rectangle) area() float64 {
    	return receiver.width * receiver.heigth
    }
    
    func main(){
    	rect := rectangle{heigth: 12,  12}
    	area := rect.area()
    	fmt.Println(area)
    }
    

    注意

    • 接收者不一样,那么method就不一样
    • method里面可以访问接收者的字段
    • 调用method通过.访问,就像struct里面访问字段一样
    • 定义在任何你自定义的类型、内置类型、struct等各种类型上面
    • 如果想要改变接受者的内容,可以使用指针

    interface

    简单的说,interface是一组method签名的组合,我们通过interface来定义对象的一组行为

    /* 定义接口 */
    type interface_name interface {
       method_name1 [return_type]
       method_name2 [return_type]
       method_name3 [return_type]
       ...
       method_namen [return_type]
    }
    
    /* 定义结构体 */
    type struct_name struct {
       /* variables */
    }
    
    /* 实现接口方法 */
    func (struct_name_variable struct_name) method_name1() [return_type] {
       /* 方法实现 */
    }
    ...
    func (struct_name_variable struct_name) method_namen() [return_type] {
       /* 方法实现*/
    }
    

    interface类型定义了一组方法,如果某个对象实现了某个接口的所有方法,则此对象就实现了此接口。

    type Isay interface {
    	say(word string) string
    }
    
    type dog struct {
    	name string
    }
    
    type cat struct {
    	sex string
    }
    
    func (d dog) say(word string) string {
    	return d.name + word
    }
    
    func (c cat) say(word string) string {
    	return "cat=" + word
    }
    
    //使用
    var idg, icat Isay
    idg = dog{"dog"}
    fmt.Println(idg.say("hello"))
    icat = cat{"0"}
    fmt.Println(icat.say("world"))
    

    最后,任意的类型都实现了空interface(我们这样定义:interface{}),也就是包含0个method的interface。

    类型判断

    Comma-ok断言

    Go语言里面有一个语法,可以直接判断是否是该类型的变量: value, ok = element.(T),这里value就是变量的值,ok是一个bool类型,element是interface变量,T是断言的类型。

    如果element里面确实存储了T类型的数值,那么ok返回true,否则返回false。

    package main
    
    import (
    	"fmt"
    	"strconv"
    )
    
    type Element interface{}
    type List [] Element
    
    type Person struct {
    	name string
    	age int
    }
    
    //定义了String方法,实现了fmt.Stringer
    func (p Person) String() string {
    	return "(name: " + p.name + " - age: "+strconv.Itoa(p.age)+ " years)"
    }
    
    func main() {
    	list := make(List, 3)
    	list[0] = 1 // an int
    	list[1] = "Hello" // a string
    	list[2] = Person{"Dennis", 70}
    
    	for index, element := range list {
    		if value, ok := element.(int); ok {
    			fmt.Printf("list[%d] is an int and its value is %d
    ", index, value)
    		} else if value, ok := element.(string); ok {
    			fmt.Printf("list[%d] is a string and its value is %s
    ", index, value)
    		} else if value, ok := element.(Person); ok {
    			fmt.Printf("list[%d] is a Person and its value is %s
    ", index, value)
    		} else {
    			fmt.Printf("list[%d] is of a different type
    ", index)
    		}
    	}
    }
    

    if-else过多,可以使用switch代替

    package main
    
    import (
    	"fmt"
    	"strconv"
    )
    
    type Element interface{}
    type List [] Element
    
    type Person struct {
    	name string
    	age int
    }
    
    //打印
    func (p Person) String() string {
    	return "(name: " + p.name + " - age: "+strconv.Itoa(p.age)+ " years)"
    }
    
    func main() {
    	list := make(List, 3)
    	list[0] = 1 //an int
    	list[1] = "Hello" //a string
    	list[2] = Person{"Dennis", 70}
    
    	for index, element := range list{
    		switch value := element.(type) {
    			case int:
    				fmt.Printf("list[%d] is an int and its value is %d
    ", index, value)
    			case string:
    				fmt.Printf("list[%d] is a string and its value is %s
    ", index, value)
    			case Person:
    				fmt.Printf("list[%d] is a Person and its value is %s
    ", index, value)
    			default:
    				fmt.Println("list[%d] is of a different type", index)
    		}
    	}
    }
    

    这里有一点需要强调的是:element.(type)语法不能在switch外的任何逻辑里面使用,如果你要在switch外面判断一个类型就使用comma-ok

  • 相关阅读:
    家庭问题(family)
    BFS简单题记
    【例2-3】围圈报数
    【例8.3】最少步数
    【例3-5】扩展二叉树
    股票买卖
    小球(drop)
    用循环单链表实现约瑟夫环
    二叉树的3种遍历6种实现
    const与#define宏常量 , inline与#define
  • 原文地址:https://www.cnblogs.com/SLchuck/p/9936900.html
Copyright © 2020-2023  润新知