???像Scala中的函数

Posted

技术标签:

【中文标题】???像Scala中的函数【英文标题】:??? like function in Scala 【发布时间】:2015-07-05 06:38:05 【问题描述】:

https://github.com/scala/scala/blob/2.11.x/src/library/scala/Predef.scala#L230

???在 scala 中是一个在 predef 中定义的函数,它抛出一个 NotImplementedError

在我的项目中,我使用 Google Guice 来注入依赖项,并认为最好有一个类似的函数,如果注入从未发生,则抛出异常,以便捕获注入器的缺失用法或缺失 @注入注解。

在我的项目中,我有一个期望被注入的类

class OScoreboard 
  @Inject
  val source :Provider[ScoreboardBuilder] = injected;

还有一个对象

class ExpectedInjectionException(message: String = null, cause: Throwable = null) extends RuntimeException

object injected extends Nothing
  def apply : Nothing = 
    throw new ExpectedInjectionException("Expected an injection")
  

但是我得到了注入的错误不是 Provider[ScoreboardBuilder] 类型的错误

我在滥用应用程序吗?在不引用注入的对象的情况下,我还能如何引用 scala 函数 apply (甚至使用不同的名称)?

另外我怀疑即使我修复了这个错误,该函数也会在注入发生之前急切地运行导致异常,这是否意味着我需要让每个注入的字段变得惰性,或者是否有其他解决方案?

编辑:


问题在于我对 Scala 的理解。

vals 是急切计算的,所以 ???-like 函数在类构造时立即执行(由于它使用字段注入,因此在注入发生之前立即发生)导致该字段永远不会被注入。

像 Java 中的 final 字段这样的值 可以 被注入,因为它只是字节码验证器的限制。可以使用 reflectionGuice 所做的)将 final 字段写入正常。

为了回答这个问题,需要一种方法来延迟 ???-like 函数/值的执行,直到第一次读取该字段。我不确定如何,或者是否有可能。另一种选择是将它们初始化为空。但这将导致 NullPointerExceptions 众所周知,这是无用的。我希望使用类似 null 的错误来解释注入失败。

【问题讨论】:

【参考方案1】:

首先:你在一个地方写了INJECTED,在另一个地方写了injected。我会假设这是一个错字,并且您对两者的意思相同。

这样的作业:

val source :Provider[ScoreboardBuilder] = INJECTED;

将不起作用,因为您试图将对象INJECTED 分配给Provider[ScoreboardBuilder] 类型的变量。对象不是那种类型,所以你不能做那个赋值。

也许您希望该对象的行为类似于一个函数,并且它的 apply 方法会自动被调用,但它不是这样工作的。

您可以将INJECTED 定义为您的类中的方法:

class OScoreboard 
  @Inject
  val source :Provider[ScoreboardBuilder] = INJECTED

  private def INJECTED : Nothing =
    throw new ExpectedInjectionException("Expected an injection")

或者你可以把它放在一个单独的对象中,但是你必须在你的类中导入它:

object injected 
  def INJECTED : Nothing =
    throw new ExpectedInjectionException("Expected an injection")


class OScoreboard 
  import injected._

  @Inject
  val source :Provider[ScoreboardBuilder] = INJECTED

【讨论】:

啊!所以将它导入文件是不够的,但您还需要将它导入到类中。此外,您已将该函数大写为 INJECTED,这是我在尝试将其交换为应用之前所拥有的 :) 谢谢。 我太早接受了。如果在注入发生之前我没有遇到函数评估的任何问题,我会接受这个作为答案。 好的,我已经开始对此进行测试,但它没有按预期工作。据我所知,一旦构造/注入类,它就会立即出错,而不是等到字段被访问。这可能是我的假设???不会立即出错,但是有没有办法解决这个问题或延迟异常直到字段被访问? @RyanTheLeach 请注意,类中的val 在您创建类的实例时(在构造函数运行时)被初始化,并且只能初始化一次。所以,你不能先用INJECTED之类的东西来初始化它,然后让一些依赖注入机制来修改它。就像 Java 中的 final 成员变量一样。您必须使用构造函数参数注入。【参考方案2】:

问题在于我对 Scala 的理解。

val 是热切计算的,所以 ???函数在类构造时立即执行(由于它使用字段注入,因此在注入发生之前立即发生)导致抛出异常。

使其变得惰性会导致使用反射进行注入,而不会在构造时引发异常。然而,生成的 Java 代码并不知道会发生这种情况。所以当第一次访问注入的值时,生成的代码将注入的引用替换为???然后继续抛出异常。

我看不到任何方法来完成这项工作。

【讨论】:

以上是关于???像Scala中的函数的主要内容,如果未能解决你的问题,请参考以下文章

一文掌握scala中的方法和函数

Scala如何将集合中的元素放入数组函数中

将变量转换为Scala“运行时评估”中的方法

Scala的高级特性

Scala API中的选项和命名默认参数是不是像油和水?

spark-sql/Scala 中的反透视列名是数字