???像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 字段这样的值 可以 被注入,因为它只是字节码验证器的限制。可以使用 reflection(Guice 所做的)将 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中的函数的主要内容,如果未能解决你的问题,请参考以下文章