关于编程:Golang-面向对象编程

43次阅读

共计 2635 个字符,预计需要花费 7 分钟才能阅读完成。

Golang 是面向对象的么?

是,也不是。只管 Go 有类型和办法,并且容许面向对象格调的编程,但没有类型层次结构。Go 的『接口』概念提供了一种不同的实现形式,在某些方面更通用。同时,短少类型层次结构使 Go 的『对象』感觉上比 C++ 或 Java 等语言中的『对象』轻很多。本文的目标就是通过示例来阐明,如何应用 Golang 进行面向对象编程

过程化

以下是一个对于身份证 ID 的示例,用于从身份证中提取生日。通常的实现版本如下:

func Birthday(id string) string {return id[6:14]
}
const (id = "412717199109031697")
func Test_Birthday(t *testing.T) {found := Birthday(id)
    wanted := "19910903"
    if found != wanted {t.Errorf("unexpected birthday, wanted:%v, found:%v", wanted, found)
    }
}

简略的数据,如此实现倒也问题不大。但生产环境中往往遇到的都是简单的多的数据和操作。此时就须要将数据和操作封装在一起

封装

Golang 中能够通过 type 关键字创立新的类型,同时应用 NewXXX 的格调创建对象。

type ID string

func NewID(id string) (ID, error) {if len(id) != 18 {return "", errors.New(fmt.Sprintf("error id length:%v", len(id)))
    }
    return ID(id), nil
}

func (i ID) Birthday() string {return string(i[6:14])
}
func TestID_Birthday(t *testing.T) {found := ID(id).Birthday()
    wanted := "19910903"
    if found != wanted {t.Errorf("unexpected birthday, wanted:%v, found:%v", wanted, found)
    }
}

当业务变得更加简单,同一种性能,存在多种实现形式,比方领取形式,微信领取、京东领取、支付宝、银联等不同渠道的大略流程大抵类似,但实现细节有所区别。此时就须要借助多态的动静绑定来进行业务形象。

多态

Golang 中动静绑定办法的惟一形式是通过接口(interface)来实现的。构造或其余具体类型上的办法始终是动态的。

type ID interface {Birthday() string
}

type id string

func NewID(i string) (ID, error) {if len(i) != 18 {return nil, errors.New(fmt.Sprintf("error id length:%v", len(i)))
    }
    return id(i), nil
}

func (i id) Birthday() string {return string(i[6:14])
}
const (fakeid = "412717199109031697")

func TestID_Birthday(t *testing.T) {
    var i ID
    i, _ = NewID(fakeid)
    found := i.Birthday()
    wanted := "19910903"
    if found != wanted {t.Errorf("unexpected birthday, wanted:%v, found:%v", wanted, found)
    }
}

除了线性的业务逻辑解决场景,在生产中还会遇到层状的业务流,然而不同档次之间又有很多性能是相通的,此时就须要借助“继承”之类的能力,来实现代码复用。遗憾的是 Golang 中并不存在继承,上面咱们介绍它的替代者

组合

在最出名的语言中,面向对象编程很多探讨是对于类型之间关系的。Go 采纳了不同的实现 —— 暗藏类式的类型依赖。

在 Go 中,类型会主动满足指定其办法子集的任何接口,无需提前申明两种类型相关联。类型能够一次满足许多接口,而没有传统的多重继承的复杂性。类型和接口之间没有明确的关系,所以不波及类型层次结构。相似想法能够用来结构像类型平安的 Unix 管道一样的实现。

所有的“继承”之类的实现,在 Golang 中都能以组合(或内嵌)的形式来实现,组合和内嵌的对象能够是具体的类型,也能够形象的接口。以下示例介绍了两种格调的实现:

type Man interface {Birthday() string
}

func NewMan(name, id string) (Man, error) {i, err := NewID(id)
    return &man{
        id:   i,
        name: name,
    }, err
}

func NewManEmbedding(name, id string) (Man, error) {i, err := NewID(id)
    return &manEmbedding{
        ID:   i,
        name: name,
    }, err
}

type man struct {
    id   ID
    name string
}

func (m *man) Birthday() string {return m.id.Birthday()
}

type manEmbedding struct {
    ID
    name string
}
const (
    peterid = "412717199109031697"
    samid   = "312717199109036148"
)

func TestMan_Birthday(t *testing.T) {peter, _ := NewMan("peter", peterid)
    sam, _ := NewMan("sam", samid)
    mans := []Man{peter, sam}
    for _, man := range mans {found := man.Birthday()
        wanted := "19910903"
        if found != wanted {t.Errorf("unexpected birthday, wanted:%v, found:%v", wanted, found)
        }
    }

}

总结

Write go in go way. Golang 很多经典的思维都能够通过官网文档取得,例如:FAQ。

源代码: https://github.com/cyningsun/…

本文作者 :cyningsun
本文地址 :https://www.cyningsun.com/03-…
版权申明:本博客所有文章除特地申明外,均采纳 CC BY-NC-ND 3.0 CN 许可协定。转载请注明出处!

正文完
 0