美文网首页
Go 面向对象、接口(二)

Go 面向对象、接口(二)

作者: LL大L | 来源:发表于2018-06-21 10:17 被阅读24次

    欢迎来我的博客

    go 语言仅支持封装,不支持继承和多态
    go 语言没有class 只有struct

    结构体

    声明和创建

    type treeNode struct {
    
        value int
        left, right *treeNode
    }
    
    func main() {
    
        var root treeNode
        root = treeNode{value: 3}
        root.left = &treeNode{}
        root.right = &treeNode{5, nil, nil}
        root.right.left = new(treeNode)
    
        nodes := []treeNode {
            {value: 3},
            {},
            {6, nil,&root   },
        }
        // [{3 <nil> <nil>} {0 <nil> <nil>} {6 <nil> 0xc4200a2020}]
        fmt.Println(nodes)
    }
    

    go 本身不提供构造函数,虽然提供了那么多构造的方式,但是还是会有使用到构造函数的需求,这时我们可以自己写一个工厂函数

    需要注意的是,这里返回了局部变量的地址,但是我们不需要关心这个变量是被分配到堆还是栈上,go内部的垃圾回收机制会帮我们解决这个问题

    func createNode(value int) *treeNode {
        return &treeNode{value: value}
    }
    

    如果需要对结构体增加扩展方法,我们可以采用以下的方式

    func (node treeNode) print() {
        fmt.Println(node.value)
    }
    
    func main() {
        var root treeNode
        root = treeNode{value: 3}
        // 3
        root.print()
    }
    

    封装

    go 语言中的封装使用名字来区分,作用域是包

    • 首字母大写代表 public
    • 首字母小写代表 private

    一个文件的目录下只能有一个包

    duck typing

    • 走路像鸭子、叫起来像鸭子、长的像鸭子,那么就是鸭子
    • 描述食物的外部行为而非内部结构
    • 严格说go属于结构化类型系统,类似duck typing

    python中的 duck typing

    运行时才知道传入的retriever有没有get方法,且需要注释来说明接口

    def download(retrivever):
        return retriever.get("www.baidu.com")
    

    c++中的 duck typing

    编译时才知道传入的retriever有没有get方法,且需要注释来说明接口

    template <class R>
    string download(const R& retriever) {
        return retriever.get("www.baidu.com")
    }
    

    java中的类似代码

    传入的参数必须实现IRetriever接口,但不是duck typing

    <R extends IRetriever>
    String download(R r) {
        return r.get("www.baidu.com")
    }
    
    

    C#中类似代码

    传入的参数必须实现IRetriever接口,但也不是duck typing

    string download(R r) where r : IRetriever {
        return r.get("www.baidu.com")
    }
    

    go语言的 duck typing

    具体实现见接口

    • 同时可以满足Readable、Appendable
    • 同时具有python、c++的duck typing的灵活性
    • 又具有java、c#的类型检查

    接口

    在下面的例子中,我们可以看出go 的interface 的实现与其他语言的区别,并遵守了duck typing

    package test
    
    type Retriever struct {
        Contents string
    }
    
    func (r Retriever) Get(url string) string {
        return r.Contents
    }
    
    package main
    
    type Retriever interface {
        Get(url string) string
    }
    
    func download(r Retriever) string {
        return r.Get("http://www.baidu.com")
    }
    
    func main() {
    
        var r Retriever
        r = test.Retriever{"test"}
        // test
        fmt.Println(download(r))
    }
    

    接口的类型

    试着输出这个接口的类型,看看接口到底是什么

    func main() {
    
        var r Retriever
        r = test.Retriever{"test"}
        // test.Retriever {test}
        fmt.Printf("%T %v\n", r, r)
    
        r = &reall.Retriever{"Mozilla/5.0", time.Minute}
        // *reall.Retriever {Mozilla/5.0 1m0s}
        fmt.Printf("%T %v\n", r, r)
    }
    
    15284544401782.jpg
    • 接口变量自带指针
    • 接口变量同样采用值传递,几乎不需要使用接口的指针
    • 指针接受者实现只能以指针方式使用,值接受者都可以

    查看接口变量

    在查看接口变量时,我们可以使用Type Assertion、Type Switch

    PS:在go语言中,interface{} 表示任何类型

    Type Switch

    func inspect(r Retriever) {
    
        switch v := r.(type) {
    
        case test.Retriever:
            fmt.Println(v.Contents)
        case *reall.Retriever:
            fmt.Println(v.UserAgent)
        }
    }
    

    Type Assertion

    if testRetriever, ok := r.(test.Retriever); ok {
        fmt.Println(testRetriever.Contents)
    } else {
        fmt.Println("this is not test retriever")
    }
    

    组合接口

    我们可以通过以下方式对接口进行组合

    type Retriever interface {
        Get(url string) string
    }
    
    type Poster interface {
        Post(url string, form map[string]string) string
    }
    
    type RetrieverPoster interface {
        Retriever
        Poster
    }
    
    func session(s RetrieverPoster) string {
    
        s.Post("http://www.baidu.com", map[string]string {"name":"rp"})
        return s.Get("http://www.baidu.com")
    }
    

    相关文章

      网友评论

          本文标题:Go 面向对象、接口(二)

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