【发布时间】:2018-10-24 04:02:12
【问题描述】:
我使用 Scala 隐式类来扩展我经常使用的对象。例如,我有一个类似于 Spark DataFrame 上定义的方法:
implicit class DataFrameExtensions(df: DataFrame) {
def deduplicate: Boolean =
df.groupBy(df.columns.map(col): _*).count
}
但是如果类已经定义了相同的方法,则不会调用隐式定义。如果我稍后升级到定义了DataFrame#deduplicate 方法的新版本的 Spark,会发生什么?客户端代码将静默切换到新的实现,这可能会导致细微的错误(或明显的错误,问题较少)。
使用反射,如果 DataFrame 在我的隐式定义之前已经定义了 deduplicate,我可以抛出 runtime 错误。然后,理论上,如果我的隐式方法与现有方法冲突,我可以检测到它并重命名我的隐式版本。但是,一旦我升级 Spark、运行应用程序并检测到问题,使用 IDE 重命名旧方法为时已晚,因为任何对 df.deduplicate 的引用现在都指的是原生 Spark 版本。我必须恢复我的 Spark 版本,通过 IDE 重命名方法,然后再次升级。不是世界末日,但不是一个伟大的工作流程。
有没有更好的方法来处理这种情况?如何安全地使用“pimp my library”模式?
【问题讨论】:
-
我相信最安全(也是最简单)的做法是使用简单的函数而不是定义隐式类。
def deduplicate(df: DataFrame): Boolean = df.groupBy(df.columns.map(col): _*).count -
不理想,但您可以使用不太可能引入的名称,例如
deduplicate_或任何其他约定。 -
这似乎是fragile base class problem 的变体,但基于隐式的丰富不会对所涉及的类强加任何显式关系。所以编译器看不出问题。
-
有点元和题外话,但有没有人觉得我们为 Scala 隐含三个不同的不相关标签感到奇怪?
-
@AndreyTyukin 使用 Scala 表达自己的方式总是太多。
标签: scala implicit implicits scala-implicits