zoukankan      html  css  js  c++  java
  • golang面向对象整理

    golang知识整理(1)---面向对象

    本文用于整理golang和面向对象有关的技术,忽略了一些与其他语言相似的特性,着重关注golang自身特性,主要包括下面几个方面:

    • struct匿名字段
    • method及其特性
    • interface及其特性

    struct匿名字段

    匿名字段是指struct中只提供类型,不提供变量名的字段,也称为嵌入字段。

    当匿名字段是一个struct的时候,那么这个struct所拥有的全部字段都被隐式地引入了当前定义的这个struct。

    type Human struct {
        name string
        age int
        weight int
    }
    
    type Student struct {
        Human  // 匿名字段,那么默认Student就包含了Human的所有字段
        speciality string
    }
    

    当匿名字段内部和外部出现同名字段时,优先访问外层的字段。

    例如:

    type Human struct {
        name string
        age int
        phone string  // Human类型拥有的字段
    }
    
    type Employee struct {
        Human  // 匿名字段Human
        speciality string
        phone string  // 雇员的phone字段
    }
    
    

    当需要调用Employee对象中Human的phone字段时,可以用如下方式访问:

    Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
    fmt.Println("Bob's work phone is:", Bob.phone)
    // 如果我们要访问Human的phone字段
    fmt.Println("Bob's personal phone is:", Bob.Human.phone)
    

    method及其特性

    golang的方法叫作method,它没有类内部的方法,method的语法如下:

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

    receiver表示调用该方法的对象类型,可以通过设置不同的receiver类型来实现多态。

    method可以设置指针作为receiver的类型,这样才可以改变receiver内部数据的值,如下所示:

    func (b *Box) SetColor(c Color) {
        b.color = c
    }
    

    另外当receiver为指针时,go可以通过指针直接访问实体的字段,而不需要转成实体,因此函数中*b.Color=c和b.Color=c都是可以的。

    如果匿名字段实现了某个method,继承这个匿名字段的类也可以调用这个method,例如:

    type Human struct {
        name string
        age int
        phone string
    }
    type Student struct {
        Human //匿名字段
        school string
    }
    //在human上面定义了一个method
    func (h *Human) SayHi() {
        fmt.Printf("Hi, I am %s you can call me on %s
    ", h.name, h.phone)
    }
    func main() {
        mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
        mark.SayHi()
    }
    

    继承了匿名字段method的方法也可以重写自己的同名method,如下所示:

    type Human struct {
        name string
        age int
        phone string
    }
    
    type Employee struct {
        Human //匿名字段
        company string
    }
    
    //Human定义method
    func (h *Human) SayHi() {
        fmt.Printf("Hi, I am %s you can call me on %s
    ", h.name, h.phone)
    }
    
    //Employee的method重写Human的method
    func (e *Employee) SayHi() {
        fmt.Printf("Hi, I am %s, I work at %s. Call me on %s
    ", e.name,
            e.company, e.phone) //Yes you can split into 2 lines here.
    }
    
    func main() {
        sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
        sam.SayHi()
    }
    

    interface及其特性

    interface是一组method的组合,我们通过interface来定义对象的一组行为。实现了interface中所有method的struct就可以说实现了这个interface。如下所示:

    type Human struct {
        name string
        age int
        phone string
    }
    //Human对象实现Sayhi方法
    func (h *Human) SayHi() {
        fmt.Printf("Hi, I am %s you can call me on %s
    ", h.name, h.phone)
    }
    
    // Human对象实现Sing方法
    func (h *Human) Sing(lyrics string) {
        fmt.Println("La la, la la la, la la la la la...", lyrics)
    }
    
    //Human对象实现Guzzle方法
    func (h *Human) Guzzle(beerStein string) {
        fmt.Println("Guzzle Guzzle Guzzle...", beerStein)
    }
    // 定义interface
    type Men interface {
        SayHi()
        Sing(lyrics string)
        Guzzle(beerStein string)
    }
    

    Human实现了Men中所有的接口,那么就可以说Human实现了Men。同时被实现的interface也可以存实现这个interface的所有对象,如下所示:

    type Men interface {
        SayHi()
        Sing(lyrics string)
    }
    
    func main() {
        mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
        paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
        sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
        tom := Employee{Human{"Tom", 37, "222-444-XXX"}, "Things Ltd.", 5000}
    
        //定义Men类型的变量i
        var i Men
    
        //i能存储Student
        i = mike
        fmt.Println("This is Mike, a Student:")
        i.SayHi()
        i.Sing("November rain")
    
        //i也能存储Employee
        i = tom
        fmt.Println("This is tom, an Employee:")
        i.SayHi()
        i.Sing("Born to be wild")
    
        //定义了slice Men
        fmt.Println("Let's use a slice of Men and see what happens")
        x := make([]Men, 3)
        //这三个都是不同类型的元素,但是他们实现了interface同一个接口
        x[0], x[1], x[2] = paul, sam, mike
    
        for _, value := range x{
            value.SayHi()
        }
    }
    

    Men、Student、Employee三个类均实现了Men接口,因此均可以用Men类型的对象来存储。

    另外,空的interface可以存储任意类,这点有点类似c++中的void*类。

    根据interface的上述特性,还可以将实现了interface的对象作为参数输入以interface为参数的函数中,以实现函数的变类型参数输入。例如fmt.Println实现变参数输入就是用如下的Stringer接口来实现的,任何实现了这个Stringer接口的对象都可以作为参数被fmt.Println调用。

    type Stringer interface {
         String() string
    }
    

    Go语言还可以通过断言语法来判断interface所存变量的类型,如下所示:

    value, ok := element.(int)
    

    类似于struct的匿名字段,interface也有一种匿名interface可以将一个interface继承至另一个interface,获得其中所有的接口,如下所示:

    type Interface interface {
        sort.Interface //嵌入字段sort.Interface
        Push(x interface{}) //a Push method to push elements into the heap
        Pop() interface{} //a Pop elements that pops elements from the heap
    }
    
  • 相关阅读:
    FFmpeg入门,简单播放器
    Linux系统编译Win32版本adb
    检测目标程序ELF bit是32还是64
    Swift编程资料全集
    Swift编程资料总结
    cocos2d-html5学习之三-为sprite添加触摸事件
    Cocos2d-html5学习笔记二
    cocos2d-x学习笔记一
    NSViewAnimation进行视图和窗口动画
    Cocoa中NSAnimation动画简介
  • 原文地址:https://www.cnblogs.com/cjh-DataCastle/p/7300834.html
Copyright © 2011-2022 走看看