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