Omk*_*ogi 2 inheritance scala case-class scopt
我想让一个案例类扩展一个特征
这是我的要求:
trait ParentParams { var name: String = "Al" }则子项不应为case class ChildParams(id: String = "whatever", override val name: String = Parent.defaultName) extends Parent。我宁愿将其作为case class Child(id: String) extends Parent。但是,当我尝试第二种方法时,当我尝试对.copy()case类对象进行操作时,我无法访问名称字段。作为一种解决方法,我可以通过以下方式更改name属性的值childObj.name = "newName" var而不是val。但是,理想情况下,我希望使其不可变,并使用copy方法更改值。这就是我现在拥有的,但是无法使用该.copy()方法来更改继承属性的值。
package abcd.wxyz
import org.scalatest.{FlatSpec, Matchers}
trait ParentTrait {
var name: String = "name"
}
case class TestParams(param1: String = "123") extends ParentTrait
class TestParamsSpec extends FlatSpec with Matchers {
"TestParams" should "be able to access it's inherited attributes and modify them" in {
val testParams = TestParams()
testParams.name = "newName1"
testParams.param1 should equal("123")
testParams.name should equal("newName1")
val modifiedTestParams = testParams.copy(name = "newName2") // cannot resolve symbol name
modifiedTestParams.name should equal("newName2")
}
}
Run Code Online (Sandbox Code Playgroud)
我在.copy(name = "newName2")上面的代码中看到“无法解析符号名称” 。
具有此继承的原因是要具有一个接受Child对象并希望其定义了“ name”属性的函数。例如,考虑一个将附加“先生”的函数。或“太太” 给定具有名称属性的Child对象。
发生的事情的总体背景:我正在使用scopt使用命令行输入值(放入案例类)填充配置。如果未提供任何值,则对该属性使用默认值。所谓属性,是指案例类中的数据成员。我有一个函数(我们称之为dbReader),该函数接受case类的对象,并使用它建立连接并从数据库中读取数据。我的项目中有许多不同的参数案例类,我希望每个参数都实现一个共同的DatabaseConnectionParameters特征,以便dbReader函数可以工作,而不管传递给它的参数案例类如何。
在Scala中,构造函数的默认值被编译为在随播对象的上下文中求值的函数,因此
case class CaseClazz(foo: String = super.bar) extends Bar
Run Code Online (Sandbox Code Playgroud)
编译成类似(为了清楚起见,我不修改名称):
class Bar { def bar: String = "whatevs" }
case class CaseClazz(foo: String = CaseClazz.defaultForFoo) extends Bar
object CaseClazz extends Function1[String, CaseClazz] {
def defaultForFoo: String = super.bar
def apply(foo: String = defaultForFoo): CaseClazz = new CaseClazz(foo)
}
Run Code Online (Sandbox Code Playgroud)
哪个不编译,因为super在对象中是CaseClazz$,它没有定义bar方法。
获得所需行为的最清晰方法是IMO:
object Parent {
val defaultName: String = "Al"
}
class Parent(val name: String = Parent.defaultName) { def parentBehavior: Unit = println("parent!") }
case class Child(id: String = "55", override val name: String = Parent.defaultName) extends Parent(name)
Run Code Online (Sandbox Code Playgroud)
这使得:
scala> Child(id = "ego").parentBehavior
parent!
scala> Child(id = "ego").name
res12: String = Al
scala> Child().name
res13: String = Al
scala> Child().parentBehavior
parent!
Run Code Online (Sandbox Code Playgroud)