案例类继承了另一个类/特征

时间:2019-05-28 15:11:03

标签: scala inheritance case-class scopt

我想让一个Case类扩展一个特征

这是我的要求:

  1. 我需要为孩子使用一个案例类。由于scopt(https://github.com/scopt/scopt
  2. ,因此这是一项艰巨的要求
  3. 父母必须是一个特质。抱歉,无法及早了解
  4. 我希望孩子可以访问父特性的属性,并且最好在声明子案例类时不必再次指定它们。例如,如果父代特征是: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()时,我无法访问名称字段。作为解决方法,我可以通过name
  5. 来更改childObj.name = "newName"属性的值
  6. 我(硬性要求)应该能够覆盖子对象从父对象继承的属性值。现在这是可能的,因为我已将父属性声明为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")

  }
}

对于以上代码,我在.copy(name = "newName2")上收到“无法解析符号名称”。

具有此继承的原因是要具有一个接受Child对象并希望其定义了“ name”属性的函数。例如,考虑一个将附加“先生”的函数。或“太太”赋予具有名称属性的Child对象。

正在发生的事情的总体背景: 我正在使用scopt用命令行输入值(进入案例类)填充配置。如果未提供任何值,则对该属性使用默认值。所谓属性,是指案例类中的数据成员。 我有一个函数(我们称它为dbReader),该函数接受case类的对象,并使用它建立连接并从数据库中读取数据。我的项目中有许多不同的参数案例类,我希望每个参数都实现一个公用的DatabaseConnectionParameters特性,以便dbReader函数可以工作,而不管将哪个参数案例类传递给它。

2 个答案:

答案 0 :(得分:6)

在scala中,构造函数的默认值被编译为在伴随对象的上下文中求值的函数,因此

case class CaseClazz(foo: String = super.bar) extends Bar

编译成类似(为了清楚起见,我不修改名称):

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)
}

由于对象中的superCaseClazz$(未定义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)

允许:

scala> Child(id = "ego").parentBehavior
parent!

scala> Child(id = "ego").name
res12: String = Al

scala> Child().name
res13: String = Al

scala> Child().parentBehavior
parent!

答案 1 :(得分:0)

case class Child(id: String = "55", override val name: String = super.name) extends Parent

不起作用,但是

 case class Child(id: String = "55", override val name: String) extends Parent(name)

确实...

您必须向Parent提供一个构造函数参数才能实例化它。

相关问题