Go 有点;方法重载“;在围棋中?
假设我得到一个名为Go 有点;方法重载“;在围棋中?,go,overloading,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()根据任何因素做出不同的
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
风格的方法来实现相同的目标 这里应该有一个接口
创建一个像
type Stateful interface {
State() string
}
和基态类型
type BaseState struct{
}
func (s BaseState) State() string{
return "Base state"
}
您可以嵌入BaseState
struct
type MyStruct struct{
BaseState
}
因此,状态
将返回“基本状态”
,但也可以实现自己的方法
func (s MyStruct) State() string{
return "New State"
}
现在状态
将返回“新状态”
这里应该有一个界面 创建一个像
type Stateful interface {
State() string
}
和基态类型
type BaseState struct{
}
func (s BaseState) State() string{
return "Base state"
}
您可以嵌入BaseState
struct
type MyStruct struct{
BaseState
}
因此,状态
将返回“基本状态”
,但也可以实现自己的方法
func (s MyStruct) State() string{
return "New State"
}
现在状态
将返回“新状态”
您也可以定义函数类型的成员值,而不是将
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())
这个例子正在进行中
现在,您可以使用PrettyName
API定义接口类型,进一步的算法/业务逻辑将调用PrettyName
type StateAPI interface {
PrettyName () string
}
要将State
类型放入StateAPI
界面,需要在私有函数成员周围定义一个简单的PrettyName
方法
func (s *State) PrettyName() string {
return s.prettyName()
}
这基本上是你最初的想法,完全合法。中有一个例子正好使用此构造。
该示例按不同字段对音乐记录进行排序,例如,按年份、按艺术家等,以便使用API
输入数据需要有三种方法
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)
}
按不同字段排序的一种方法是为每个案例定义一种自定义数据类型,例如ByYear
,ByArtist
,等等,并为每个案例定义所有三种API方法。但是Len
和Swap
方法对于所有情况都是多余的。更好的解决方案是只使用函数成员定义一种自定义数据类型
//!+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
的含义
源代码是而不是
struct
上的prettyName
作为方法,您还可以定义函数类型的成员值
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())
这个例子正在进行中
现在,您可以使用PrettyName
API定义接口类型,进一步的算法/业务逻辑将调用PrettyName
type StateAPI interface {
PrettyName () string
}
要将State
类型放入StateAPI
界面,需要在私有函数成员周围定义一个简单的PrettyName
方法
func (s *State) PrettyName() string {
return s.prettyName()
}
这基本上是你最初的想法,完全合法。中有一个例子正好使用此构造。
该示例按不同字段对音乐记录进行排序,例如,按年份、按艺术家等,以便使用API
输入数据需要有三种方法
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)
}
按不同字段排序的一种方法是为每个案例定义一种自定义数据类型,例如ByYear
,ByArtist
,等等,并为每个案例定义所有三种API方法。但是Len
和Swap
方法对于所有情况都是多余的。更好的解决方案是只使用函数成员定义一种自定义数据类型
//!+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
的含义
源代码是您考虑过接口吗?@mkopriva,您的意思是,有许多
状态行为
,状态行为
,…-所有驱动相同的IState
接口的方法,在Go
的情况下,仅公开相同签名和名称的相同数量的方法?正确,但如果您只想对一个方法执行此“重载”,则可以将接口嵌入状态,然后根据“任意因素”设置实现@mkopriva,每个行为不需要一个命名的instace吗?另外,我这样做的方式允许动态构建对象-不需要命名实例,但我可以将其他代码绑定到IState
接口。您考虑过接口吗?@mkopriva,您的意思是,有许多statebehavior
,statebehavior
,…-所有驱动相同的IState
接口的方法,在Go
的情况下,仅公开相同签名和名称的相同数量的方法?正确,但如果您只想对一个方法执行此“重载”,则可以将接口嵌入状态,然后根据“任意因素”设置实现@mkopriva,每个行为不需要一个命名的instace吗?另外,我这样做的方式允许动态构建对象-不需要命名实例,但我可以将其他代码绑定到IState
接口。