使用与参数类型相同的类型参数和带有匹配表达式的参数类型

时间:2019-06-30 03:18:33

标签: scala generics type-parameter

通过编译以下示例代码会出错。

abstract class Base
case class A(i: Int)    extends Base
case class B(s: String) extends Base

class Transform {
  def func[T <: Base](arg: T): T = arg match {
    case A(i) => A(i)
    case B(s) => B(s)
  }
}

错误是

Example.scala:9: error: type mismatch;
 found   : A
 required: T
    case A(i) => A(i)
                  ^
Example.scala:10: error: type mismatch;
 found   : B
 required: T
    case B(s) => B(s)
                  ^
two errors found

这些错误是合理的。
为避免这种情况,我需要将asInstanceOf[T]放在类似A(i).asInstanceOf[T]的实例化后面。但是,如果有很多区分大小写的模式,那么对于所有返回值都这样做是很烦人的。

此外,我想使用Transform类作为父类并重写func()以执行特定的操作,如下面的代码。

class ExtTransform extends Transform {
  override def func[T <: Base](arg: T): T = arg match {
    case A(i) => A(i + 1)
    case _    => super.func(arg)
  }
}

有更好的方法或技巧吗?

2 个答案:

答案 0 :(得分:3)

  

为避免这种情况,我需要将asInstanceOf [T]放在实例化之后,例如A(i).asInstanceOf [T]。但是,如果有很多区分大小写的模式,那么对于所有返回值都这样做是很烦人的。

这个问题很容易解决:在比赛结束时将它放在一个位置,而不是每个分支。

override def func[T <: Base](arg: T): T = (arg match {
  case A(i) => A(i)
  case B(s) => B(s)
}).asInstanceOf[T]

但是请注意,您的设计本质上是不安全的,因为除了BaseBaseA之外还有B的子类型:单例类型(a.type ),复合类型(A with SomeTraitNull ...,其中任何一种都可以用作T。最好有过载:

class Transform {
  def func(arg: Base): Base = arg match {
    case arg: A => func(arg)
    case arg: B => func(arg)
  }

  def func(arg: A): A = arg
  def func(arg: B): B = arg
}

class ExtTransform extends Transform {
  override def func(arg: A): A = A(arg.i + 1)
}

答案 1 :(得分:0)

我建议改用 typeclass

- GODEBUG=netdns=go