scala - 从 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
}
}
}
据我了解,该示例从抽象类创建一个新的匿名类WithBrowser
并实例化它。该实例将接收(命名的)构造函数参数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
,但示例中未声明类型参数。相反,匿名类的实例使用命名构造函数参数接收此信息webDriver
。类型参数和构造函数参数之间缺少什么链接?- 该示例声明了一个代码块(它只是返回
true
),这个代码块就是测试本身。但是该代码在匿名类中的什么位置?WithBrowser
扩展Around
并覆盖around
执行代码块的函数,但我不明白生成的匿名类如何将给定的示例代码块移动到around
.
非常感谢任何帮助。
解决方案
Scala 可以推断类型参数。由于传递的参数的类型都与类型参数无关,因此会限制要推断的类型,因此 scala 编译器只会将其推断为 type
Nothing
。代码块通常是类的构造函数,但这是一种特殊情况。该类
Around
确实扩展了scala.DelayedInit
接口。这会将构造函数中的代码重写为delayedInit
函数调用。实际上将是构造函数的代码作为按名称调用的参数传递给此函数。这个值(实际上包装在一个org.specs2.execute.Result.resultOrSuccess
调用中)是传递给around
函数的参数。
想象一下这样的Around
课程:
class Around extends DelayedInit {
def delayedInit(f: => Unit): Unit = around(f)
def around(f: => Unit): Unit
}
假设您现在将继承 around 类:
class Foo extends Around {
println("Hello World")
}
上面被重写为:
class Foo extends Around {
delayedInit(println("Hello World"))
}
如果我的解释不够清楚,或者您想了解更多实施细节:
- 这里是Around
和DelayedInit
文档。
推荐阅读
- xml - Xpath 查找两个属性匹配的以下兄弟姐妹
- vb.net - VB.Net以日期格式查找月份的最后一天
- r - 获取 Google 搜索结果编号
- php - 当似乎不在 PHPMailer、TLS、Openssl、file_get_contents 中时,LetsEncrypt 证书无效/过期,2021 年 9 月 30 日
- java - 可以进一步优化 onDraw() 方法吗?
- javascript - NextJS 应用程序在页面刷新时抛出错误
- azure - 我想检查我对 azure 的理解
- javascript - Javascript方法未按预期切换
- javascript - worker.js 文件不处理在 Heroku 上发送给它的作业
- python - 如何根据 MultiIndex DataFrame 的条件删除 1 级索引