Каков идиоматический способ создания сложной иерархии структур в Go?

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

Object
--Immovable
----Building
----Mountain
--Movable
----Car
----Bike

вот как вышеуказанная иерархия реализуется способом "пустой метод".

type Object interface {
  object()
}

type Immovable interface {
  Object
  immovable()
}

type Building struct {
  ... 
}

type Mountain struct {
  ... 
}

type Movable interface {
  Object
  movable()
}

type Car struct {
  ...
} 

type Mountain struct {
  ...
} 

func (*Building) object() {}
func (*Mountain) object() {}
func (*Car) object() {}
func (*Bike) object() {}
func (*Building) immovable() {}
func (*Mountain) immovable() {}
func (*Car) movable() {}
func (*Bike) movable() {}    

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

в комментариях указано, что пустые методы запрещают назначение несовместимых типов. В нашем примере *Car не может быть назначен *Immovable например.

это так просто и в других языках, таких как C++, который поддерживает наследование. Я не могу придумать другого способа представить АСТ.

способ реализации компилятора Go AST может быть идиоматическим,но не менее прямым?

1 ответов


Go is не (совсем) объектно-ориентированный язык: это не занятия и не имеет наследования типа; но он поддерживает аналогичную конструкцию под названием вложение на и