Inheritance Go中创建复杂结构层次结构的惯用方法是什么?

Inheritance Go中创建复杂结构层次结构的惯用方法是什么?,inheritance,go,struct,interface,embedding,Inheritance,Go,Struct,Interface,Embedding,我正在用Go编写一个解释器,我正在寻找存储AST的惯用方法。我阅读了Go编译器的源代码,似乎他们使用了带有空方法的接口来表示AST。例如,我们有以下层次结构 Object --Immovable ----Building ----Mountain --Movable ----Car ----Bike 这就是以“空方法”方式实现上述层次结构的方式 上面的代码是一个人为的例子,这就是Go编译器如何使用几十个空方法来编译AST。但是为什么呢?注意定义了多少个空方法。随着层次结构深度的增加,它可能变得

我正在用Go编写一个解释器,我正在寻找存储AST的惯用方法。我阅读了Go编译器的源代码,似乎他们使用了带有空方法的接口来表示AST。例如,我们有以下层次结构

Object
--Immovable
----Building
----Mountain
--Movable
----Car
----Bike
这就是以“空方法”方式实现上述层次结构的方式

上面的代码是一个人为的例子,这就是Go编译器如何使用几十个空方法来编译AST。但是为什么呢?注意定义了多少个空方法。随着层次结构深度的增加,它可能变得非常复杂

注释中指出,空方法不允许分配不兼容的类型。例如,在我们的示例中,
*汽车
不能分配给
*不可移动的

<>这在C++等其他语言中是很容易的,支持继承。我想不出任何其他方式来代表AST

Go编译器AST的实现方式可能是惯用的,但它不是不那么直截了当吗

围棋是:它没有课,它是;但是它在
struct
级别和
interface
级别上都支持一个类似的结构,称为嵌入,并且它确实有

围棋中只有固定的方法集。若类型的方法集是接口的超集(并没有意图声明),则类型隐式实现接口

如果您想显式地记录或声明您的类型确实实现了接口(因为它没有显式地声明),空方法是非常好的。官方的

如果您希望在类型层次结构中进行区分(例如,您不希望允许对象同时是
可移动的
不可移动的
),则它们必须具有不同的方法集(在
可移动的
不可移动的
的每个方法集中必须至少有一个在另一个方法集中不存在的方法),因为如果方法集包含相同的方法,一个方法的实现也会自动实现另一个方法,因此您可以将
Movable
对象分配给
Immovable
类型的变量

假设不将此类方法添加到其他类型,则向具有相同名称的接口添加空方法将提供这种区别

减少空方法的数量 就我个人而言,我对空方法没有任何问题。但是,有一种方法可以减少它们

如果您还为层次结构中的每种类型创建了一个
struct
实现,并且每个实现将
struct
实现嵌入到更高一级,则更高一级的方法集将自动出现,无需进一步ado:

对象
Object
接口和
ObjectImpl
实现:

type Object interface {
  object()
}
type ObjectImpl struct {}
func (o *ObjectImpl) object() {}
type Immovable interface {
    Object
    immovable()
}
type ImmovableImpl struct {
    ObjectImpl // Embed ObjectImpl
}
func (o *Immovable) immovable() {}
type Building struct {
    ImmovableImpl // Embed ImmovableImpl struct

    // Building-specific other fields may come here
}
固定的
Immovable
接口和
ImmovableImpl
实现:

type Object interface {
  object()
}
type ObjectImpl struct {}
func (o *ObjectImpl) object() {}
type Immovable interface {
    Object
    immovable()
}
type ImmovableImpl struct {
    ObjectImpl // Embed ObjectImpl
}
func (o *Immovable) immovable() {}
type Building struct {
    ImmovableImpl // Embed ImmovableImpl struct

    // Building-specific other fields may come here
}
注意
immovablempl
仅添加
immovable()
方法,
object()
是“继承的”

建筑
建筑
实施:

type Object interface {
  object()
}
type ObjectImpl struct {}
func (o *ObjectImpl) object() {}
type Immovable interface {
    Object
    immovable()
}
type ImmovableImpl struct {
    ObjectImpl // Embed ObjectImpl
}
func (o *Immovable) immovable() {}
type Building struct {
    ImmovableImpl // Embed ImmovableImpl struct

    // Building-specific other fields may come here
}
建筑
不会添加任何新方法,但它会自动成为一个不可移动的对象


如果“子类型”的数量增加,或者如果接口类型有不止一个“标记”方法(因为所有方法都是“继承的”),这种技术的优势将大大增加。

谢谢您的回答。但是我怎么能重新考虑我对非OO语言的设计呢?@unnamed\u addr你是说Go?空方法有什么问题?我在输入更多的内容时没有任何问题,但我认为我用了错误的方法。这就是我问这个问题的原因。@unnamed_addr我编辑了我的答案,向您展示了如何减少空方法的“技巧”。这样你只需要写一次,它们是“继承的”。