我有一个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) Modifier trait 不应扩展 Function1,而应定义其自己的抽象 def apply[X](element: El): Unit
方法。由于幻像类型参数 X,未应用 SAM 语法。
2) 添加一个无意义的抽象 protected[this] def foo
到 Modifier trait。这将使 SAM 语法不适用,如果我正确理解 Scala.js 死代码消除,这个伪造的方法将从运行时消除。
我倾向于选项 1,因为它似乎减轻了 Modifier 实现者的负担,而且更明显的是它不会影响运行时性能。
但它仍然看起来很老套,而且我不喜欢无用的 phantom 类型会泄漏到我的库的 API 中。有没有更好的办法?
感谢您的任何建议。
最佳答案
从 Scala 2.12 的文档中可以看出 Sam Conversions precedes implicits :文档还讨论了覆盖此行为的潜在解决方案。
如果您需要自动进行转换,两种方法都是合理的:
如果您扩展自己的自定义
MyFunction1
,您可能会失去标准库的组合优势如果您添加一个无意义的方法,一旦您使用定义在
上的方法执行组合操作,您将回退到标准 Function1Function1
在您的情况下,我想这两种方法都可以,因为您的 Modifier apply
正在返回 Unit 并且您不会将这些操作通过管道或连接在一起。
关于scala - 防止 Scala 特征成为 SAM 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48971622/