gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 01:09:04 25 4
gpt4 key购买 nike

我正在用 Go 编写一个解释器,我正在寻找存储 AST 的惯用方式。我阅读了 Go 编译器源代码,似乎他们使用带有空方法的接口(interface)来表示 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 编译器的工作方式 implemented带有许多空方法的 AST。但为什么?注意定义了多少个空方法。随着层级深度的增加,它可能会变得非常复杂。

评论中指出,空方法不允许分配不兼容的类型。例如,在我们的示例中,*Car 不能分配给 *Immovable

这在其他支持继承的语言(如 C++)中非常容易。我想不出任何其他表示 AST 的方法。

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

最佳答案

Go 是 not (quite) an object oriented language : 它没有类并且它 does not have type inheritance ;但它在 struct 级别和 interface 级别都支持称为 embedding 的类似构造,并且它确实有 methods .

Interfaces在 Go 中只是固定的方法集。如果类型的方法集是接口(interface)的超集(没有意图声明),则类型隐式实现接口(interface)。

如果您想记录明确声明您的类型确实实现了一个接口(interface)(因为它没有明确声明),那么空方法非常有用。官方Go FAQ: How can I guarantee my type satisfies an interface?

type Fooer interface {
Foo()
ImplementsFooer()
}

如果你想在你的类型层次结构中有所区别(例如,你不想让一个对象既是Movable又是Immovable),它们必须有不同的方法集合(MovableImmovable 的每个方法集中必须至少有 1 个方法不存在于另一个方法集中),因为如果方法集将包含相同的方法,一个的实现也会自动实现另一个,因此您可以将 Movable 对象分配给 Immovable 类型的变量。

将空方法添加到具有相同名称的接口(interface)将为您提供这种区别,前提是您不会将此类方法添加到其他类型。

减少空方法的数量

就我个人而言,我对空方法没有任何问题。不过有一种方法可以减少它们。

如果您还为层次结构中的每个类型创建一个结构 实现,并且每个实现都嵌入 结构实现上一层,上一层的方法集自动来,不用多说:

对象

Object 接口(interface)和ObjectImpl 实现:

type Object interface {
object()
}
type ObjectImpl struct {}
func (o *ObjectImpl) object() {}

不动产

Immovable 接口(interface)和ImmovableImpl 实现:

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

注意 ImmovableImpl 只增加了 immovable() 方法,object() 是“继承”的。

建筑

构建实现:

type Building struct {
ImmovableImpl // Embed ImmovableImpl struct

// Building-specific other fields may come here
}

注意 Building 不添加任何新方法,但它自动成为一个 Immovable 对象。

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

关于inheritance - Go 中创建复杂结构层次结构的惯用方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29144622/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com