美文网首页
GO 语言接口与结构体 - interface & struct

GO 语言接口与结构体 - interface & struct

作者: 坚果jimbowhy | 来源:发表于2019-08-02 22:06 被阅读0次

    interface & struct 接口与结构体

    以继承为特点的 OOP 只是编程世界的一种抽象方式,在 Golang 的世界里没有继承,只有组合和接口,并且是松散的接口结构,不强制声明实现接口,这看起来更符合 Java 之父 Gosling 的设想。

    If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.

    翻译过来就是:如果某个东西长得像鸭子,像鸭子一样游泳,像鸭子一样嘎嘎叫,那它就可以被看成是一只鸭子。

    单一继承关系解决了 is-a 也就是定义问题,因此可以把子类当做父类来对待。但对于父类不同但又具有某些共同行为的数据,单一继承就不能解决了,C++ 采取了多继承这种复杂的方式。

    GO 采取更贴近现实世界的网状结构,不同于继承,GO 语言的接口是松散的结构,它不和定义绑定。从这一点上来说,Duck Type 相比传统的 extends 是更加松耦合的方式,可以同时从多个维度对数据进行抽象,找出它们的共同点,使用同一套逻辑来处理。

    接口使用例子,定义MyString类型与string一样,再实现 VolwelsFInder 接口的方法,使用时只需要实例化对象并赋予接口即可以访问接口规范的方法,rune 是基本数据类型格式 Unicode 字符:

    package main
    
    import (  
        "fmt"
    )
    
    //定义interface 
    type VowelsFinder interface {  
        FindVowels() []rune
    }
    
    type MyString string
    
    // 实现接口
    func (ms MyString) FindVowels() []rune {  
        var vowels []rune
        for _, rune := range ms {
            if rune == 'a' || rune == 'e' || rune == 'i' || rune == 'o' || rune == 'u' {
                vowels = append(vowels, rune)
            }
        }
        return vowels
    }
    
    func main() {  
        name := MyString("Sam Anderson") // 类型转换
        var v VowelsFinder               // 定义一个接口类型的变量
        v = name 
        fmt.Printf("Vowels are %c", v.FindVowels())
    }
    

    所有类型都实现了空接口 Empty Interface 表示为interface {},因此可以对任何类型进行类型断言 Type Assertions,但要先转换成接口在进行类型断言检查。类型断言检查是对接口类型进行的动态类型检查,语法格式 x.(T),T 就是断言类型,通过断言检查就可以从操作数中得到具体的类型数据。如下面尝试将变量类型 s 转换成 string,先将 s 转换成空接口interface{}(v),再进行 .(string) 断言:

    val, ok := interface{}(v).(string)
    

    GO 语言的结构体 struct 是组合非继承,不像其它 OOP 语言那样通过继承机制实现类结构的扩展。

    下面例程中,Being 是最基础的结构体,Human 组合了 Being,而 Student 又组合了 Human。 但是通过 Human.Eat() 方法调用 Drink() 只能是 Human.Drink()。如果 Student 也实现了 Eat 方法并调用 Dranking(),则会调用自己的 Student.Dranking()。

    对 s 分别进行了 Human、Student 类型断言,输出结果可以看到,s 断言 Human 是不成功的,因为它是 Student 类型。断言 IHuman 接口也是成功的,因为 Student 结构实现了 IHuman 接口的所以方法。也就是说看起来叫起来都像鸭子的东西,那就可以认为它是鸭子

    package main
     
    import "fmt"
     
    func main(){
        var h Human
     
        s := Student{Grade: 1, Human: Human{Name: "Jason", Age: 12, Being: Being{IsLive: true}}}
        fmt.Println("student:", s)
        fmt.Println("student ", s.Name, " is alive:", s.IsLive )
     
        // h = s // cannot use s (type Student) as type Human in assignment
        fmt.Println(h)
     
        // Heal(s) // cannot use s (type Student) as type Being in argument to Heal
        Heal(s.Human.Being) // true
     
        s.Drink() // student drinking...
        s.Eat() // human eating... & human drinking...
    
        human, b := interface{}(s).(Human) // false s is Student but Human
        fmt.Println(human, b)
         
        student, b := interface{}(s).(Student)
        fmt.Println(student, b)
    
        ihuman, b := interface{}(s).(IHuman)
        fmt.Println(ihuman, b)
    
    }
     
    type Being struct {
        IsLive bool
    }
     
    type Human struct {
        Being
        Name string
        Age int
    }
    
    func (h Human) Eat(){
        fmt.Println("human eating...")
        h.Drink()
    }
     
    func (h Human) Drink(){
        fmt.Println("human drinking...")
    }
     
    type Student struct {
        Human
        Grade int
    }
    
    func (s Student) Drink(){
        fmt.Println("student drinking...")
    }
    
    func Heal(b Being){
        fmt.Println(b.IsLive)
    }
    
    type IHuman interface {
        Eat()
        Drink()
    }
    

    相关文章

      网友评论

          本文标题:GO 语言接口与结构体 - interface & struct

          本文链接:https://www.haomeiwen.com/subject/jwordctx.html