Scala 集合的元素可以使用命名参数和默认值构造同级实例?

亚当麦克勒

我想要一个对象集合,每个对象都是一个不同类的伴侣,这些类都共享一个在超类中定义的通用方法,可以在使用foreach(). 我希望这些兄弟类的构造函数彼此具有相同的命名参数和默认参数值最后,我想尽量减少重复的代码。

到目前为止,我正在尝试使用案例类来做到这一点,因为——如果它有效——它将消除每种类型的伴随对象的所有重复代码。问题是,如果我将所有这些伴随对象放入 a 中Set,当我再次取出它们时,我会丢失默认参数和参数名称。

这是我所描述的一些示例代码:

trait MyType {
  val param: String
  def label = param   // all instances of all subclasses have this method
}

case class caseOne(override val param: String = "default") extends MyType
case class caseTwo(override val param: String = "default") extends MyType

object Main extends App {
  // I can construct instances using the companion objects' `apply()` method:
  val works1 = caseOne(param = "I have been explicitly set").label
  // I can construct instances that have the default parameter value
  val works2 = caseOne().label

  // But what I want to do is something like this:
  val set = Set(caseOne, caseTwo)
  for {
    companion <- set
  } {
    val fail1 = companion()                      // Fails to compile--not enough arguments
    val fail2 = companion(param = "not default") // Fails also as param has lost its name
    val succeeds = companion("nameless param")   // this works but not what I want
    println(fail1.label + fail2.label)           // this line is my goal
  }
}

值得注意的是,如果Set只有一个元素,那么它会编译,这表明多元素的推断类型Set缺少参数名称——即使它们是相同的——和默认值。还建议如果我提供了Set正确的类型参数,这可能会起作用。但是那种类型会是什么?不是MyType因为那是伴随类的类型,而不是Set.

我可以明确定义伴随对象,但这是我想要避免的重复代码。

如何循环遍历我的集合,MyType在每次迭代中构造子类的实例,并使用具有我想要的参数名称和默认值的构造函数?同时尽量减少重复代码?

更新:最初示例代码显示caseOne并且caseTwo具有不同的默认值param那是不正确的;他们现在是一样的。

丹·西蒙

由于您对自动生成的伴生对象没有太多控制权,因此您将无法获得您想要的确切信息。特别是要使其发挥作用,他们都需要扩展一个共同的特征。这就是为什么当集合有多个伴生对象时它无法编译的原因;尽管它们都有一个具有相同签名的方法,但它们并没有扩展编译器可以使用的共同特征。

您可以使用嵌套的案例类并获得非常相似的内容:

trait MyType {
  val param: String
  def label = param   // all instances of all subclasses have this method
}

abstract class MyTypeHelper(default: String) {

  case class Case(param: String) extends MyType

  def apply(param: String) : Case = Case(param)
  def apply(): Case = apply(default)
}

object One extends MyTypeHelper("default one")
object Two extends MyTypeHelper("default two")

object Example {

  val works1 = One(param = "I have been explicitly set").label
  val works2 = One().label

  val set = Set(One, Two)
  for {
    companion <- set
  } {
    val a = companion()                      
    val b = companion(param = "not default") 
    val c = companion("nameless param")   
    println(a.label + b.label)           
  }
}

相反,具有的caseOne类型,你有One.Case,但它仍然工具MyType,所以你不应该有任何问题,其他地方使用该特性的代码。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章