Вроде "метод перегрузки" в Go? - PullRequest
0 голосов
/ 23 декабря 2018

Предполагая, что я получил тип с именем State:

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

вместе с определенным для него методом:

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

В настоящее время я не могу изменить prettyName()ПоведениеЯ знаю, что Go преднамеренно избегает ООП-подобного наследования и перегрузки методов, и это, вероятно, никогда не изменится, но все же: что если мне нужно, чтобы prettyName() вел себя по-разному в зависимости от какого-либо фактора?Единственное решение, которое я вижу:

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

Есть ли лучший способ в стиле Go для достижения той же цели?

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Вместо 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()
}

Это в основномВаша оригинальная идея, и она абсолютно законна.В книге «1024 * go» Алан А. А. Донован и Брайан В. Керниган приведен пример именно с этой конструкцией.В этом примере музыкальная запись сортируется по разным полям, например, по году, по исполнителю и т. Д. Чтобы использовать API sort.Sort ,

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)
}

Один из способов сортировки по разным полям - определить один пользовательский тип данных для каждого случая, скажем, 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.

Исходный код здесь

0 голосов
/ 23 декабря 2018

Здесь должен работать интерфейс.

создавая интерфейс типа

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

...