gpt4 book ai didi

scala - scala 中的 Mixin 与组合

转载 作者:行者123 更新时间:2023-12-03 05:17:24 26 4
gpt4 key购买 nike

在 Java 世界中(更准确地说,如果您没有多重继承/混合),经验法则非常简单:“优先考虑对象组合而不是类继承”。

我想知道如果你也考虑混入,尤其是在 scala 中,它是否/如何改变?
mixin 是否被视为多重继承或更多类组合的一种方式?
是否还有“优先考虑对象组合而不是类组合”(或相反)准则?

我见过很多例子,人们使用(或滥用)mixin,而对象组合也可以完成这项工作,但我并不总是确定哪个更好。在我看来,你可以用它们实现非常相似的事情,但也有一些差异,一些例子:

  • 可见性 - 通过 mixins,所有内容都成为公共(public) api 的一部分,而组合则不是这样。
  • 冗长 - 在大多数情况下,mixins 不太冗长并且更容易使用,但情况并非总是如此(例如,如果您还在复杂的层次结构中使用 self 类型)

我知道简短的答案是“这取决于”,但可能有一些典型的情况,这个或那个更好。

到目前为止我可以提出的一些指南示例(假设我有两个特征 A 和 B,并且 A 想使用 B 中的一些方法):

  • 如果你想使用 B 中的方法扩展 A 的 API,则使用 mixins,否则组合。但如果我创建的类/实例不是公共(public) API 的一部分,则没有任何帮助。
  • 如果您想使用一些需要 mixins 的模式(例如 Stackable Trait Pattern ),那么这是一个简单的决定。
  • 如果你有循环依赖,那么带有 self 类型的 mixin 会有所帮助。 (我试图避免这种情况,但这并不总是那么容易)
  • 如果您想要一些动态的运行时决定如何进行组合,那么对象组合。

在许多情况下,mixin 似乎更容易(和/或不那么冗长),但我很确定它们也有一些陷阱,例如“God class”和两篇 artima 文章中描述的其他陷阱:part 1 , part 2 (顺便说一句,在我看来,大多数其他问题与 scala 无关/不那么严重)。

您还有更多类似的提示吗?

最佳答案

如果您仅将抽象特征混合到类定义中,然后在对象实例化时混合相应的具体特征,则在 Scala 中可以避免人们在混合时遇到的许多问题。例如

trait Locking{
// abstract locking trait, many possible definitions
protected def lock(body: =>A):A
}

class MyService{
this:Locking =>
}

//For this time, we'll use a java.util.concurrent lock
val myService:MyService = new MyService with JDK15Locking

这个结构有几个值得推荐的地方。首先,它可以防止类的爆炸,因为需要不同的特征功能组合。其次,它允许轻松测试,因为人们可以创建并混合“无所事事”的具体特征,类似于模拟对象。最后,我们对我们服务的消费者完全隐藏了所使用的锁定特征,甚至锁定正在进行。

既然我们已经克服了大多数声称的混合缺点,我们仍然需要权衡介于混合和合成之间。就我自己而言,我通常根据假设的委托(delegate)对象是否完全由包含对象封装,或者它是否可以共享并具有自己的生命周期来做出决定。锁定提供了完全封装委托(delegate)的一个很好的例子。如果您的类使用锁对象来管理对其内部状态的并发访问,则该锁完全由包含对象控制,并且它及其操作都不会作为类的公共(public)接口(interface)的一部分进行公布。对于像这样完全封装的功能,我使用混合。对于共享的内容(例如数据源),请使用组合。

关于scala - scala 中的 Mixin 与组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3422606/

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