Golang встроенные структуры

можно ли наследовать методы типа без использования встроенных структур?

первый фрагмент кода-это рабочий код, который встраивает Property struct в Node и я могу назвать node.GetString это метод на Properties. Мне это не нравится, когда я инициализирую Node Я(?) инициализировать Properties структура в ее пределах. Есть ли способ обойти это?

package main

import "fmt"

type Properties map[string]interface{}

func (p Properties) GetString(key string) string {
    return p[key].(string)
}

type Nodes map[string]*Node

type Node struct {
    *Properties
}

func main() {
    allNodes := Nodes{"1": &Node{&Properties{"test": "foo"}}} // :'(
    singleNode := allNodes["1"]
    fmt.Println(singleNode.GetString("test"))
}

в конечном счете, я хотел бы сделать нечто вроде следующего. Где Node типа Properties и инициализация не требует инициализации Property структура тоже. Следующий код не работает, но может быть ясно, какова моя цель.

package main

import "fmt"

type Properties map[string]interface{}

func (p Properties) GetString(key string) string {
    return p[key].(string)
}

type Nodes map[string]*Node

type Node Properties

func main() {
    allNodes := Nodes{"1": &Node{"test": "foo"}} // :)
    singleNode := allNodes["1"]
    fmt.Println(singleNode.GetString("test")) // :D
}

Я буду добавлять больше структур, которые будут использовать Propertiesметоды, поэтому я и спрашиваю. Если бы я только ... --3-->, у меня просто были бы методы для Node и было сделано. Но потому что у меня будет больше, чем Node Я считаю излишним добавлять одни и те же методы ко всем структурам, которые вставляют Properties

Я думаю, что больше к точной проблеме, я хочу использовать Properties методы Node без инициализации Properties.

2 ответов


Итак, вы сталкиваетесь с идиосинкразией Go here. Встраивание-единственный способ, которым методы одной структуры могут "продвигаться", чтобы казаться существующими в другой структуре. В то время как он интуитивно чувствует, что type Node Properties следует подвергнуть Properties методы on Node, этот эффект этого синтаксиса для Node чтобы взять на себя макет памяти Properties но не любой из его методов.

это не объясняет, почему этот выбор дизайна был сделан, но Перейти Spec по крайней мере специфический если сухой. Если Вы читаете его точно так, как кажется, без интерпретации, это очень точно:

набор методов типа интерфейса является его интерфейсом. Набор методов любого другого типа T состоит из всех объявленных методов с типом приемника t

GetString имеет приемник типа Properties не Node, серьезно, интерпретируйте спецификацию, как будто вы бухгалтер без воображения. При этом сказано:

дополнительные правила применитесь к структурам, содержащим анонимные поля, как описано в разделе о типах структур.

...

поле или метод F анонимного поля в структуре x называется повышенным, если x.f-это юридический селектор, который обозначает это поле или метод f.

повышенные поля действуют как обычные поля структуры, за исключением того, что они не может использоваться в качестве имен полей в составных литералах структуры.

учитывая тип структуры S и тип с именем T, продвигаемые методы входит в набор методов структуры следующим образом:

  • если S содержит анонимное поле T, наборы методов S и *S оба включите повышенные методы с приемником T. набор методов *s также включает в себя продвигаемые методы с receiver * T.
  • если S содержит анонимный поле *T, наборы методов S и * S включают в себя продвигаемые методы с приемником T или *т.

эта строка о составных литералах - это то, что заставляет вас объявлять Properties внутри каждого Node создать.

p.s. Привет, Джефф!


короткий ответ на ваш последний вопрос-это просто нет.

существует большая разница между объявлением типа и внедрением в golang, вы можете сделать свой последний пример работы вручную сделать преобразование типа между Node и Properties:

package main

import "fmt"

type Properties map[string]interface{}

func (p Properties) GetString(key string) string {
    return p[key].(string)
}

type Nodes map[string]*Node

type Node Properties

func main() {
    allNodes := Nodes{"1": &Node{"test": "foo"}} // :)
    singleNode := allNodes["1"]
    fmt.Println(Properties(*singleNode).GetString("test")) // :D
}

но ясно, что это не то, что вы хотите, вы хотите встраивание структуры с синтаксисом псевдонима типа, что невозможно в golang, Я думаю, что вы должны застрял с вашим первым подходом и игнорировать тот факт, что код является избыточным и уродливым .