zoukankan      html  css  js  c++  java
  • 从OOP的角度看Golang

    资料来源

    https://github.com/luciotato/golang-notes/blob/master/OOP.md?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

    Golang中的概念

    Golang中引入了在Golang中独有的struct 和 interface,其意义和传统语言中的不同。

    概念清单

    Golang Classic OOP
    struct class with fields, only non-virtual methods
    interface class without fields, only virtual methods
    embedding multiple inheritance AND composition
    receiver implicit this parameter

    struct 是一个class但是没有virtual方法

    struct 是一个class但是没有virtual方法,比如说:

    type Rectangle struct {
        Name string
        Width, Height float64
    }
    func(r Rectangle) Area() float64 {
        return r.Width + r.Height
    }
    

    那么伪代码如下:

    class Rectangle
      field Name: string
      field Width: float64
      field Height: float64
      method Area() //non-virtual
         return this.Width * this.Height
    

    构造器

    • 对于每一个基本类型,默认使用0来填充,如果你没有显示的指定其初始值,那么就是0
    • 没有指定的类的构造器,只是对每一个类的实例,都有一个通用的构造器。使用类似于JSON格式的字面值常量来构造
    
    function construct ( class,  literal)
    
      helper function assignFields ( object, literal)  //recursive
        if type-of object is "object"
            if literal has field-names
                for each field in object.fields
                    if literal has-field field.name
                        assignFields(field.value,  literal.fields[field.name].value) //recurse
            else
            //literal without names, assign by position
                for n=0 to object.fields.length
                    assignFields(object.fields[n].value,  literal.fields[n].value) //recurse
        else
            //atom type
            set object.value = literal.value
    
    // generic constructor main body
    var classInstance = new class
    assignFields(classInstance, literal)
    return classInstance
    

    对于Golang的构造器使用

    
    package main
    
    import . "fmt"
    
    type Rectangle struct {
        Name          string
        Width, Height float64
    }
    func main() {
        var a Rectangle
        var b = Rectangle{"I'm b.", 10, 20}
        var c = Rectangle{Height: 12, Width: 14}
        Println(a)
        Println(b)
        Println(c)
    }
    

    Golang中的嵌入类似于OOP中的没有virtual 方法的多继承

    将一个结构体嵌入到另一个结构体,就好像是对非虚成员的多继承。让我们看看一个例子:

    type base struct {
        a string
        b int
    }
    type derived  {
        base  //嵌入
        d int   
        a float32 //隐藏base中的a字段 
    }
    
    func main() {
        var x derived;
        fmt.Printf("%T", x.a) // x.a float32
        fmt.Printf("%T", x.base.a) //=> x. 
    }
    

    当base结构体嵌入到derived结构体中,那么base结构体中的字段和方法都可以在derived结构体中都可用。但是base内部的字段可以被derived中的字段shadowed。在内部,有一个名称叫base 类型为base的字段被创建,。如果将base嵌入到了derived,那么在derived类型可以直接访问base的字段。

    Shadowing表示在derived中定义另一个与base 字段和方法相同名字的字段和方法,那么就会存在shadowinig这种情况。一但base中的字段被derived中的shadow,那么可以通过使用base名称来访问隐藏的字段。所有base中的字段,都可以通过隐藏字段的名称base来访问。需要注意的事情:

    It is important to note that all inherited methods are called on the hidden-field-struct. It means that a base method cannot see or know about derived methods or fields. Everything is non-virtual.

    当和结构体和嵌入这种概念打交道的时候,我们应该知道所有的东西都是在编译期间静态绑定的,所以的引用解析都是在静态编译期间。

    When working with structs and embedding, everything is STATICALLY LINKED. All references are resolved at compile time.

    多层嵌入

    type NamedObj struct {
        Name string
    }
    
    type Shape struct {
        NameObj
        color string
        isRegular bool
    }
    
    type Point struct {
        x, y float64
    }
    
    type Rectangle struct {
        NameObj
        Shape
        center Point
        Width float64
        Height float64
    }
    func main() {
        var aRect = Rectange {
            NameObj{"name1"},
            Shape{NameObj{"name2"}, 0, true},
            Point{0, 0},
            20,
            2.5
        }
        fmt.Println(aRect.Name)
        fmt.Println(aRect.Shape)
        fmt.Println(aRect.Shape.Name)
    }
    

    等效的伪代码:

    class NamedObj
       field Name: string
    
    class Shape
       inherits NamedObj
       field color: int32
       field isRegular: bool
    
    class Rectangle
       inherits NamedObj
       inherits Shape
       field center: Point
       field Width: float64
       field Height: float64
    

    var aRect Rectangle中,

    • aRect.Name and aRect.NamedObj.Name 指的是同意对象
    • aRect.color and aRect.Shape.color 指的是同一个东西
    • aRect.name and aRect.NamedObj.name 指的是同一个字段, 但是 aRect.NamedObj.name 和 aRect.Shape.NamedObj.name 是不同的字段
    • aRect.NamedObj and aRect.Shape.NamedObj 是相同的类型,但是对象不同

    方法隐藏

    由于所有的golang-struct都是non-virtual的,所以你不可以覆盖这些方法。(当然接口是可以的)比如在NameObj中定义了一个名字叫做show的方法,但是呢,你在struct Rectangle中也定义了其他的方法,那么
    Rectangle/show()将会隐藏NameObj/show方法。正如基类的字段一样,你也可以通过使用基类的名称来访问基类被隐藏的方法。

    type base struct {
        a string
        b int
    }
    func (this base) xyz(){
        fmt.Println("xyz, a is ",   this.a);
    }
    // method display
    func (this base) display() {
        fmt.Println("base, a is:", this.a)
    }
    type derived struct {
        base // embedding
        d    int
        a    float32 //-SHADOWED
    }
    // method display 
    func(this derived) display() {
        fmt.Println("derived a is ", this.a)
    }
    
    func main() {
        var a derived = derived{base{"base-a", 10}, 20, 2.5}    
        a.display()  // 2.5
        a.base.diplay() // base, a is : base-a
        a.xyz(); // call base.xyz(), xyz, a is : base-a
    }
    

    Golang 方法和接受者

    Golang的 struct-method,和类的non-virtual方法类似,但是在如下地方不同:

    • struct-method在struct外面定义
    • 既然起在struct body外面定义,那么在方法中有了一个名字叫做接受者
    • 对于这个接受者的名字,自己可以取一个简单的,一般是struct类型的第一个单词
    type NameObj struct {
        Name string
    }
    func(n NameObj) show(){
        fmt.Println(n.Name)
    }
    

    struct 和 interface

    Golang中的interface是一个没有字段的,只有虚方法。interface的设计是为了补充struct。在Golang中

    **Structs: ** classes, with fields, ALL NON-VIRTUAL methods **Interfaces: ** classes, with NO fields, ALL VIRTUAL methods

    通过严格限定struct是没有virtual的方法,interface是包含所有virtual的方法,通过嵌入来将两者结合起来,从而实现多态。

    Interface

    Golang interface 是一个没有字段的类,但是包含所有是virtual的函数。考虑到这种定义,那么你能够用interface干的事情:

    • 声明一个变量的类型为 type interface
    • 实现该interface,在一个struct中实现所有该interface定义的方法
    • 嵌入到另一个interface

    空接口

    在Golang中空接口是没有任何字段和没有任何方法,所以任何struct和基本类型都实现了interface{},这意味着var x interface{}可以容纳任何类型的值。那么我们可以使用interface{}来干什么事情呢?本来什么事情都不可以干,但是我们可以使用type switchtype assertion或反射

    使用struct embedding

    当你使用struct embedding,那么你就是要创建一个multi-root 体系,通过多继承。你要记住的是,所有的结构体方法都是non-virtual的。这就是为什么struct永远要比使用接口嵌入要快。因为没有接口涉及的时候,所有的函数的调用都是在编译期间就决定了。

  • 相关阅读:
    vim黏贴代码格式混乱的解决方法
    fopen()和fclose()的用法
    简谈switch case
    【转】如何确定Kafka的分区数、key和consumer线程数
    【转】Kafka producer原理 (Scala版同步producer)
    【转】 使用maven创建web项目
    【转】使用Eclipse构建Maven项目 (step-by-step)
    eclipse的安装环境及eclipse下maven的配置安装
    strtol,strtoll,strtoul, strtoull字符串转化成数字
    Kafka Producer相关代码分析【转】
  • 原文地址:https://www.cnblogs.com/bofengqiye/p/6073943.html
Copyright © 2011-2022 走看看