Go中的Kinda“方法超载”?

时间:2018-12-22 21:09:06

标签: go overloading

假设我有一个名为State的类型:

type State struct {
    // ... does not matter what is inside
}

以及在其上定义的方法:

func (s *State) prettyName() string {
    return "I am a state!"
}

目前,我无法改变prettyName()的行为。我知道Go故意逃避了类似于OOP的继承和方法重载,并且这种情况可能永远不会改变,但是仍然:如果我需要prettyName()根据不同的因素采取不同的行为怎么办?我看到的唯一解决方案是:

type State struct {
    _prettyName func() string
}
func (s *State) prettyName() string {
    return s._prettyName()
}

是否有更好的Go风格的方法可以实现相同的目标?

2 个答案:

答案 0 :(得分:3)

一个界面应该在这里工作。

创建类似的界面

type Stateful interface  {
    State() string
}

和基本状态类型

type BaseState struct{
}
func (s BaseState) State() string{
    return "Base state"
} 

您可以嵌入BaseState结构

type MyStruct struct{
    BaseState
}

这样State将返回"Base state",但也可以实现自己的方法。

func (s MyStruct) State() string{
    return "New State"
} 

现在State将返回"New State"

https://play.golang.org/p/QOajW0O6gIz

答案 1 :(得分:0)

您也可以定义函数类型的成员值,而不是将prettyName作为struct上的方法。

type State struct {
    prettyName func() string
}

然后您可以在运行时将其值设置为任何函数

a := State{}
a.prettyName = func() string {
    return "I am a state!"
}
fmt.Println(a.prettyName())
a.prettyName = func() string {
    return "another state"
}
fmt.Println(a.prettyName())

此示例位于playground

现在您可以使用PrettyName API定义接口类型,并且进一步的算法/业务逻辑将调用PrettyName

type StateAPI interface {
    PrettyName () string
}

要使您的State类型适合StateAPI界面,您需要在私有函数成员周围定义一个简单的PrettyName方法

func (s *State) PrettyName() string {
    return s.prettyName()
}

这基本上是您的原始想法,并且完全合法。 go programming language book by Alan A. A. Donovan and Brian W. Kernighan中有一个与此结构完全相同的示例。 该示例按不同字段(例如,按年份,按艺术家等)对音乐记录进行排序。为了使用sort.Sort API,

func Sort(data Interface)

输入数据需要三种方法

type Interface interface {
        // Len is the number of elements in the collection.
        Len() int
        // Less reports whether the element with
        // index i should sort before the element with index j.
        Less(i, j int) bool
        // Swap swaps the elements with indexes i and j.
        Swap(i, j int)
}

一种按不同字段排序的方法是为每种情况定义一种自定义数据类型,例如ByYearByArtist等。并为每种情况定义所有三种API方法。但是LenSwap方法在所有情况下都是多余的。更好的解决方案是仅使用函数成员定义一种自定义数据类型,

//!+customcode
type customSort struct {
    t    []*Track
    less func(x, y *Track) bool
}
func (x customSort) Less(i, j int) bool { 
     return x.less(x.t[i], x.t[j]) }
func (x customSort) Len() int           {
     return len(x.t) }
func (x customSort) Swap(i, j int)      {
     x.t[i], x.t[j] = x.t[j], x.t[i] }

然后,您可以以编程方式控制less的含义。

源代码为here