gpt4 book ai didi

oop - 嵌入golang是否违反得墨忒耳法则?

转载 作者:IT王子 更新时间:2023-10-29 00:40:26 24 4
gpt4 key购买 nike

这就是 Effective GO 关于 Embedding 在 golang 中的说法

When we embed a type, the methods of that type become methods of the outer type, but when they are invoked the receiver of the method is the inner type, not the outer one

我有一个代码片段,其中我将 Struct User 定义如下

type User struct {
Name string
Password string
*sql.Tx
}

然后我调用 u.Query("some query here") 等。我专门这样做是为了避免像 u.Transaction.Query("query"),这显然违反了Demeter 法则。现在,在阅读了文档和有效的 go 之后,我也对第一种方法的优点表示怀疑。我是否违反了Demeter 法则?如果是,我该如何避免?

最佳答案

嵌入概念有点违反Law of Demeter因为它不隐藏一个类型被嵌入的事实如果类型本身是导出。请注意,嵌入未导出的类型不会违反 LoD(您不能引用未导出的字段和方法)。

但这不会强制您以同样违反 LoD 的方式引用提升的字段或方法。嵌入本身只是一种技术,因此您可以将通用的共享代码“外包”给其他类型;或者从另一个角度来看,在创建新类型时使用其他类型。您引用嵌入类型的提升字段或方法的方式可能违反法律。

如您所说,如果您将其称为 u.Tx.Query(),这显然违反了迪米特法则:您正在使用实现细节User 嵌入了 *sql.Tx

但是如果你这样调用它:u.Query() 没问题。这种形式没有暴露或利用 *sql.Tx 被嵌入的事实。如果实现更改并且 *sql.Tx 将不再嵌入,此表单将继续工作(例如,它更改为“常规”字段或完全删除,以及 User.Query () 方法已添加)。

如果您不想允许访问导出的嵌入类型的字段值,请将其设置为未导出的常规字段并添加一个“显式”User.Query() 方法,该方法可以委托(delegate)到现场,例如:

type User struct {
Name string
Password string
tx *sql.Tx // regular field, not embedded; and not exported
}

func (u *User) Query(query string, args ...interface{}) (*sql.Rows, error) {
return u.tx.Query(query, args...)
}

补充说明:

在这个例子中,如果使用了u.Query(),如果User的内部结构发生改变,使用它的客户端不会受到影响(如果u.Query()表示一个提升的方法或者它表示User的一个方法,即:User.Query())。

如果 sql.Tx 发生变化,是的,u.Query() 可能不再有效。但是不兼容的 sql.Tx 不太可能发生。如果您是已更改包的开发人员,并且进行了不兼容的更改,则您有责任更改依赖于您的不兼容更改的其他代码。这样做(正确更新 u.Query())调用 u.Query() 的客户端不会受到影响,客户端仍然不需要知道发生了什么变化在引擎盖下。

这正是 LoD 所保证的:如果您使用 u.Query() 而不是 u.Tx.Query(),如果 User 在内部更改,调用 u.Query() 的客户端不需要知道或担心。 LoD 不是坏事。你不应该放弃它。你可以选择你遵循的原则,但你也应该思考,而不是不惜任何代价一直遵循所选原则所要求的一切。

还有一点需要明确:LoD 不涉及 API 不兼容的更改。它提供的是,如果遵循,一个实体的内部变化将不会对使用该实体“公共(public)”面孔的其他实体产生影响。如果 sql.Tx 发生剧烈变化,Tx.Query() 将不再可用,则 LoD 不会“涵盖”该情况。

关于oop - 嵌入golang是否违反得墨忒耳法则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33232516/

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