防止 Scala 特征成为 SAM 类型

Prevent a Scala trait from qualifying as a SAM type

我有一个trait Modifier[-A] extends (A => Unit)

但是,Scala 2.12 magic SAM 语法会默默地将任何 lambda 文字(如 el => foo)转换为 Modifier,因为 Modifier 符合 SAM 类型(此语法的适用规则是 here)。

我不希望这种转换应用于我的修饰符特征,因为它会干扰我的库的语法。简而言之,我有一个从 A => Modifier[A]Modifier[A] 的隐式转换。在 2.12 中,不会为 lambda 文字(例如 thisNode => someModifier(thisNode, otherParam))触发该转换,因为 Scala 将 A => Modifier[A] lambda 本身魔术化为 Modifier[A],而不是正确的。

我知道有几种方法可以解决这个问题:

1) 修饰符特征不应该扩展 Function1,而是应该定义自己的抽象 def apply[X](element: El): Unit 方法。由于幻像类型参数 X,未应用 SAM 语法。

2) 给Modifier trait添加一个无意义的抽象protected[this] def foo。这将使 SAM 语法不适用,如果我正确理解 Scala.js 死代码消除,这个伪造的方法将从运行时消除。

我倾向于选项 1,因为它似乎减轻了 Modifier 的实施者的负担,而且更明显的是它不会影响运行时性能。

但它仍然看起来很老套,而且我不喜欢无用的幻影类型会泄漏到我的库的 API 中。有没有更好的办法?

感谢任何建议。

正如您从 Scala 2.12 的文档中看到的那样Sam Conversions precedes implicits:该文档还讨论了覆盖此行为的潜在解决方案。

如果您需要自动进行转换,两种方法都是合理的:

  1. 如果您扩展自己的自定义 MyFunction1 您可能会失去标准库的组合优势

  2. 如果添加无意义的方法,一旦使用Function1

    [=27上定义的方法执行组合操作,您将回退到标准Function1 =]

在您的情况下,我想这两种方法都可以,因为您的 Modifier apply 正在返回 Unit 并且您不会将这些操作通过管道或连接在一起。