- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
这就是 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/
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 4年前关闭。 Improve t
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
在面向对象的编程中,“基类”是派生其他类的类(http://en.wikipedia.org/wiki/Base_class)。 但是,基类的反面是什么?换句话说,什么是没有任何子类的类? 编辑:我正
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 8年前关闭。 Improve this questi
据我了解,OOP 是大型项目最常用的范式。我也知道大系统的一些较小的子集使用其他范式(例如 SQL,它是声明性的),并且我也意识到在较低级别的计算 OOP 并不真正可行。但在我看来,通常更高级别的解决
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
最近听说OOP(Java)有9条规则。我只知道四种:抽象、多态、继承和封装。 OOP 还有更多规则吗? 最佳答案 看来您正在寻找的是 Principles of Object-Oriented Des
我曾经在一次采访中被问到“OOP 的 3 个主要概念是什么?”。我回答说,我认为有4个,如下: 继承 封装 抽象 多态性 我说得对吗? 最佳答案 语言要成为面向对象有3个要求: 仅支持封装(对象)的语
我有一个关于特定 OOP 问题的组织的简单问题。 假设我有一个地形类,里面充满了瓷砖。 Tile 类有多个派生类,即 Door。 Door 类有一个名为 open() 的方法,用于打开门,还有一个名为
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
我是 Go 的新手,然后我通过示例搜索了很多如何拥有带有静态函数/变量的静态类,例如 C#。但是,我找不到任何可以很好地回答它的东西。也许这个问题看起来很愚蠢,但我不喜欢不确定或不完全理解某事。 假设
我曾尝试搜索此问题的答案,但很难用语言表达,而且许多问题要么是关于如何创建类,要么是关于如何做非常具体的事情。我需要更多的实用概述 - 我是自学成才的,我了解对象是什么(以及如何创建它们),但我从未见
在开始编码之前,我通常会尝试在没有太多分析(没有图表)的情况下进行 TDD。通常我发现自己将一个类拆分为其他类以分离关注点。我想知道更深入的分析是否会阻止这种情况。我认为大部分面向对象分析无法预测其中
在阅读单例时,我发现这个解释是使用单例的原因: since these object methods are not changing the internal class state, we can
如这里所述 https://standardofnorms.wordpress.com/2012/09/02/4-pillars-of-object-oriented-programming/ 并作为
我是这个网站的新手,所以如果我在发布问题时做错了什么,请告诉我,以便我下次修复。 我很好奇从单个基类继承多个类是否是糟糕的 OOP 实践。这可能不太合理,所以我要详细说明一下。 例如,假设您正在设计一
我对“工厂相关”设计模式及其 OOP 实现的理解一直很简单。 一个 《工厂法》是类内部的一个方法,它有一个接口(interface)(或抽象类)作为返回类型,并根据一些内部逻辑构造实现该接口(inte
C# 中的“密封”关键字,Java 中的 Final。 因为我几乎从不创建任何图表并且我只使用已经完成的类(来自框架)我多年后仍然不知道为什么有人会“锁定”一个类所以它永远不会被扩展/继承。 它是有益
我正在研究面向对象的概念,抽象概念基本上被描述为对用户隐藏实现。因此,如果类中有一个成员函数并且我们为某些任务调用该函数,抽象表示用户不应该关心事情是如何完成的,而应该只知道正在完成什么。但即使在非面
我是一名优秀的程序员,十分优秀!