Inheritance Go中创建复杂结构层次结构的惯用方法是什么?
我正在用Go编写一个解释器,我正在寻找存储AST的惯用方法。我阅读了Go编译器的源代码,似乎他们使用了带有空方法的接口来表示AST。例如,我们有以下层次结构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。但是为什么呢?注意定义了多少个空方法。随着层次结构深度的增加,它可能变得
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我编辑了我的答案,向您展示了如何减少空方法的“技巧”。这样你只需要写一次,它们是“继承的”。