当类依赖于隐式时,是否存在将类转换为Object的惯用方法?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当类依赖于隐式时,是否存在将类转换为Object的惯用方法?相关的知识,希望对你有一定的参考价值。
我是Scala的新手。
我有一系列执行UI测试的测试类,以及一系列包含可重用辅助方法的类。
示例测试类:
class MyCoolTestClass extends FreeSpec {
//Note: This driver needs to be configurable by the test in some way.
implicit val driver:WebDriver = new ChromeDriver()
val myCoolPage = new MyCoolPage
//Tests below rely on myCoolPage methods
}
示例助手类:
class MyCoolPage(implicit driver:WebDriver) {
def clickElement1(){
//relies on driver
}
def assertElement2Enabled(){
//relies on driver
}
}
现在,没有一个辅助类实际上具有可变状态。这使我想将它们从class
es转换为object
s。
但是,我能弄清楚如何做到这一点的唯一方法是为每个方法添加一个implicit WebDriver
参数。这很有效,但很难看。有没有更简洁的方法来实现我想要的东西?或者,是否有一种更惯用的方式来完全组织这个测试类/助手方法关系?
我认为,正如你所问,没有惯用的方法将class
es转换为object
s。以下是我对以下原因的看法:
你在driver
中声明了一个属性MyCoolClass
,你正在使用这些方法。因此你的class
实际上有状态。 WebDriver
是state injected进入MyCoolPage
。根据注入的WebDriver
的实现,处理方法调用的方式可能会有所不同。
要克服这一点,你需要将WebDriver
作为你的每个方法的隐含参数,正如你自己发现的那样。但是,这将允许在运行时从外部替换驱动程序。这会违反Open-Closed-Principle,我认为这比使用你的class
构造更不惯用。
如果将来再次遇到此问题,您可能会尝试在不使用implicit
的情况下编写代码。如果它仍然是将class
改为object
的合适方式,那么你可能会很高兴。
您可以将帮助类更改为对象,并仍然为成员方法提供implicit
值。
object MyCoolPage {
private val driver :WebDriver = implicitly[WebDriver]
def clickElement1() = ??? //relies on driver
def assertElement2Enabled() = ??? //relies on driver
}
但随后implicit
声明必须退出测试类。想到两种可能性:WebDriver
对象......
object WebDriver {
implicit val wd :WebDriver = new ChromeDriver()
...
......或在专用物体中。
object MyCoolPage {
import MyTestImplicits._
private val driver :WebDriver = implicitly[WebDriver]
...
总而言之,我不相信它会值得付出努力。
考虑将MyCoolPage
转换为具有抽象隐式驱动程序字段的特征,如此
trait MyCoolPage {
implicit val driver: WebDriver
def clickElement1() = {
//relies on driver
}
def assertElement2Enabled(){
//relies on driver
}
}
然后让MyCoolTestClass
扩展MyCoolPage
并使用自定义配置的驱动程序覆盖driver
字段,如下所示
class MyCoolTestClass extends FreeSpec with MyCoolPage {
override implicit val driver: WebDriver = new ChromeDriver()
//Tests below rely on myCoolPage methods
}
现在MyCoolTestClass
可以访问MyCoolPage
中的每个方法,并且这些方法不需要隐式驱动程序参数。
现在,没有一个辅助类实际上具有可变状态。这使我想将它们从
class
es转换为object
s。
但他们确实有州。是的,它是不可变的,但大多数案例类的状态也是如此,Option
s,List
s ......它们都不应该被转换成object
s。我不认为有一个解决方案比你开始时更好。
但是,这里有一个选项:将辅助对象嵌套在超类中:
abstract class AbstractTestClass extends FreeSpec {
// may optionally be implicit or non-abstract
val driver: WebDriver
object MyCoolPage {
def clickElement1(){
//relies on driver
}
def assertElement2Enabled(){
//relies on driver
}
}
object MyCoolPage2 ...
}
class MyCoolTestClass extends AbstractTestClass {
override val driver: WebDriver = new ChromeDriver()
// can use MyCoolPage methods
}
请注意,object
s是懒洋洋地加载的,所以如果MyCoolTestClass
不使用MyCoolPage2
它将不会支付它。权衡是必须在单个文件中定义所有辅助类。
以上是关于当类依赖于隐式时,是否存在将类转换为Object的惯用方法?的主要内容,如果未能解决你的问题,请参考以下文章
当我们在范围内存在多个不明确的隐式时,Scala 编译如何选择隐式