Scala层次结构分解和类型参数

时间:2014-02-18 09:43:12

标签: oop scala pattern-matching class-hierarchy

我有以下类层次结构。

sealed trait Foo {
  val a: String 
}
case class Bar1(a: String) extends Foo
case class Bar2(a: String) extends Foo 

现在我想添加一个方便的方法来修改字段a。我需要在超类型Foo中访问此方法,并且我想使用case类的.copy方法(因为我实际上有更多的字段,并且使用构造函数很痛苦) 。我的第一次尝试是使用模式匹配:

sealed trait Foo {
  val a: String
  def withField(b: String) = this match {
    case b1: Bar1 => b1.copy(a = b)
    case b2: Bar2 => b2.copy(a = b)
  }
}

现在我还希望我的withField方法返回调用者的实例类型,B1如果方法是由B1类型的实例调用的,B2如果方法是由B2Foo类型的实例调用的话,如果这是我所知道的。所以我想我可能能够将方法withField参数化以实现此目的。类似的东西:

sealed trait Foo {
  val a: String
  def withField[A <: Foo](b: String) = this match {
    case b1: Bar1 => b1.copy(a = b)
    case b2: Bar2 => b2.copy(a = b)
  }
}

但我无法使用withField类型对this进行参数设置。

我在这里完全错了吗?我可以使用override修饰符来使用不同的模式吗?

非常感谢

1 个答案:

答案 0 :(得分:2)

  

我在这里完全错了吗?我应该使用不同的模式吗?可能使用覆盖修饰符?

是。有两种选择:

sealed trait Foo {
  val a: String
  def withField(b: String): Foo
}

case class Bar1(a: String) extends Foo {
  // return types are covariant, and Bar1 is subtype of Foo,
  // so this is legal
  def withField(b: String): Bar1 = ...
}

sealed trait Foo[ThisType <: Foo[ThisType]] {
  val a: String
  def withField(b: String): ThisType
}

case class Bar1(a: String) extends Foo[Bar1] {
  def withField(b: String): Bar1 = ...
}

注意第二个更复杂,只应在实际需要的时候使用。

编辑回答克里斯蒂安的问题:

sealed trait Foo {
  type ThisType <: Foo
  def withField(b: String): ThisType = (this match {
    case b1: Bar1 => b1.copy(a = b)
    ...
  }).asInstanceOf[ThisType]
}

case class Bar1(a: String) extends Foo {
  type ThisType = Bar1
}

我不喜欢它:它需要一个强制转换,实际使用它会需要依赖的方法类型,如果它在实践中崩溃我也不会感到惊讶(例如因为编译器无法证明{{1} }和foo.ThisType是一样的。)