在 Scala 中从抽象 class 创建匿名 class - 脱糖代码
Creating an anonymous class from an abstract class in Scala - desugaring code
这里是 Scala 菜鸟。
我不理解以下摘自 Play 应用程序集成测试 (Scala) 的代码:
package workflows.admin
import play.api.test._
class SignInSpec extends PlaySpecification {
"An activated user" should {
"be able to sign in to the admin console" in new WithBrowser(webDriver = WebDriverFactory(FIREFOX)) {
// some matchers here ...
true
}
}
}
据我了解,该示例从抽象 class WithBrowser
创建了一个新的匿名 class 并将其实例化。该实例将接收(命名的)构造函数参数 webDriver
.
问题是我在查看 WithBrowser
:
时不明白这里发生了什么
abstract class WithBrowser[WEBDRIVER <: WebDriver](
val webDriver: WebDriver = WebDriverFactory(Helpers.HTMLUNIT),
val app: Application = GuiceApplicationBuilder().build(),
val port: Int = Helpers.testServerPort) extends Around with Scope {
def this(
webDriver: Class[WEBDRIVER],
app: Application,
port: Int) = this(WebDriverFactory(webDriver), app, port)
implicit def implicitApp: Application = app
implicit def implicitPort: Port = port
lazy val browser: TestBrowser = TestBrowser(webDriver, Some("http://localhost:" + port))
override def around[T: AsResult](t: => T): Result = {
try {
Helpers.running(TestServer(port, app))(AsResult.effectively(t))
} finally {
browser.quit()
}
}
}
我有两个问题:
WithBrowser
是带有类型参数 WEBDRIVER
的泛型抽象 class,但示例中未声明类型参数。相反,匿名 class' 实例使用命名的构造函数参数 webDriver
接收此信息。类型参数和构造函数参数之间缺少什么link?
- 该示例声明了一个代码块(它只是 returns
true
),这个代码块就是测试本身。但是该代码在匿名 class 中放在哪里? WithBrowser
扩展了 Around
并覆盖了执行代码块的 around
函数,但我不明白生成的匿名 class 如何将给定的示例代码块移动到 around
.
非常感谢任何帮助。
Scala 可以推断类型参数。由于传递参数类型的 none 在某种程度上与类型参数相关,因此会限制要推断的类型,因此 Scala 编译器只会将其推断为类型 Nothing
.
代码块通常是class的构造函数,但这是一个特例。 Around
class 确实扩展了 scala.DelayedInit
接口。这会将构造函数中的代码重写为 delayedInit
函数的调用。实际上是构造函数的代码作为按名称调用的参数传递给此函数。这个值(实际上包含在 org.specs2.execute.Result.resultOrSuccess
调用中)是传递给 around
函数的参数。
想象一下 Around
class 是这样的:
class Around extends DelayedInit {
def delayedInit(f: => Unit): Unit = around(f)
def around(f: => Unit): Unit
}
假设您现在将继承 class:
class Foo extends Around {
println("Hello World")
}
上面被重写为:
class Foo extends Around {
delayedInit(println("Hello World"))
}
如果我的解释不够清楚或者您想了解更多实现细节:
- 这是 Around
and the DelayedInit
文档。
这里是 Scala 菜鸟。
我不理解以下摘自 Play 应用程序集成测试 (Scala) 的代码:
package workflows.admin
import play.api.test._
class SignInSpec extends PlaySpecification {
"An activated user" should {
"be able to sign in to the admin console" in new WithBrowser(webDriver = WebDriverFactory(FIREFOX)) {
// some matchers here ...
true
}
}
}
据我了解,该示例从抽象 class WithBrowser
创建了一个新的匿名 class 并将其实例化。该实例将接收(命名的)构造函数参数 webDriver
.
问题是我在查看 WithBrowser
:
abstract class WithBrowser[WEBDRIVER <: WebDriver](
val webDriver: WebDriver = WebDriverFactory(Helpers.HTMLUNIT),
val app: Application = GuiceApplicationBuilder().build(),
val port: Int = Helpers.testServerPort) extends Around with Scope {
def this(
webDriver: Class[WEBDRIVER],
app: Application,
port: Int) = this(WebDriverFactory(webDriver), app, port)
implicit def implicitApp: Application = app
implicit def implicitPort: Port = port
lazy val browser: TestBrowser = TestBrowser(webDriver, Some("http://localhost:" + port))
override def around[T: AsResult](t: => T): Result = {
try {
Helpers.running(TestServer(port, app))(AsResult.effectively(t))
} finally {
browser.quit()
}
}
}
我有两个问题:
WithBrowser
是带有类型参数WEBDRIVER
的泛型抽象 class,但示例中未声明类型参数。相反,匿名 class' 实例使用命名的构造函数参数webDriver
接收此信息。类型参数和构造函数参数之间缺少什么link?- 该示例声明了一个代码块(它只是 returns
true
),这个代码块就是测试本身。但是该代码在匿名 class 中放在哪里?WithBrowser
扩展了Around
并覆盖了执行代码块的around
函数,但我不明白生成的匿名 class 如何将给定的示例代码块移动到around
.
非常感谢任何帮助。
Scala 可以推断类型参数。由于传递参数类型的 none 在某种程度上与类型参数相关,因此会限制要推断的类型,因此 Scala 编译器只会将其推断为类型
Nothing
.代码块通常是class的构造函数,但这是一个特例。
Around
class 确实扩展了scala.DelayedInit
接口。这会将构造函数中的代码重写为delayedInit
函数的调用。实际上是构造函数的代码作为按名称调用的参数传递给此函数。这个值(实际上包含在org.specs2.execute.Result.resultOrSuccess
调用中)是传递给around
函数的参数。
想象一下 Around
class 是这样的:
class Around extends DelayedInit {
def delayedInit(f: => Unit): Unit = around(f)
def around(f: => Unit): Unit
}
假设您现在将继承 class:
class Foo extends Around {
println("Hello World")
}
上面被重写为:
class Foo extends Around {
delayedInit(println("Hello World"))
}
如果我的解释不够清楚或者您想了解更多实现细节:
- 这是 Around
and the DelayedInit
文档。