具有特征匹配的Scala通用

时间:2018-10-22 19:14:07

标签: scala generics traits

看看这段代码。

trait SomeMix {

}

trait Processor[T] {

  def processMix(t: T with SomeMix) = {
    println("processing T with Mix")
  }

  def processAsUsual(t:T)= {
    println("processing T")
  }

  def process(t:T) = {
    t match {
      case mix: SomeMix => processMix(mix) // <---- error here 
      case _ => processAsUsual(t)
    }
  }
}

愚蠢的Scala编译器在此处显示错误:

错误:(22,39)类型不匹配;  找到:mix.type(具有基础类型SomeMix)  必需:T与SomeMix       案例混合:SomeMix => processMix(mix)

我不知道我匹配SomeMix的表达式已经是T类型。Ok可以帮助他。更改的代码:

   def process(t:T) = {
    t match {
      case mix: T with SomeMix => processMix(mix) // <---- warning here 
      case _ => processAsUsual(t)
    }
  }

现在,它同意一切正确,但显示警告:

警告:(22,17)抽象类型模式T未选中,因为通过擦除将其消除了       案例混合:使用SomeMix => processMix(mix)

有什么好的方法可以避免错误和警告吗?

4 个答案:

答案 0 :(得分:2)

Scala编译器并不愚蠢。由于类型擦除,您无法检查t是T with SomeMix的实例。代替动态类型分派,请尝试将类型类与静态分派一起使用。

例如

trait SomeMix {
  def someMethod: String = "test2"
}

class SomeType

def process[T](t: T)(implicit P: Process[T]): Unit = P.process(t)

trait Process[T] {
  def process(t: T): Unit
}

implicit val processString: Process[SomeType] = s =>
  println(s"processing $s as usual")
implicit val processStringWithSomeMix: Process[SomeType with SomeMix] = s =>
  println(s"processing $s with mix ${s.someMethod}")

process(new SomeType)
process(new SomeType with SomeMix)

答案 1 :(得分:1)

喜欢吗?

var counter=0;
while (true) {
for (i = 0; i < 5; i++) {
debugger; //enter this through Chrome Dev then press CTRL s to save
counter++;
}
}

答案 2 :(得分:1)

您可以像@ppressives建议的那样在编译时执行此操作。 如果您真的想在运行时执行此操作,则应该找到一种在编译后将类型保留在那里的方法。用Scala的标准方法是TypeTags

尝试

import reflect.runtime.universe.{TypeTag, typeOf}

def typ[A: TypeTag](a: A) = typeOf[A]

def process(t: T)(implicit ev: TypeTag[T with SomeMix], ev1: TypeTag[T]) = {
  t match {
    case mix if typ(t) <:< typeOf[T with SomeMix] => processMix(mix.asInstanceOf[T with SomeMix])
    case _ => processAsUsual(t)
  }
}

val p = new Processor[Int] {}
p.process(10) //processing T

val p1 = new Processor[Int with SomeMix] {}
val ten = 10.asInstanceOf[Int with SomeMix]
p1.process(ten) //processing T with Mix

检查

Pattern match of scala list with generics

Pattern matching on generic type in Scala

答案 3 :(得分:1)

由于您已经提到,它肯定是T的一个实例,因此您可以取消取消选中的警告:

case mix: (T @unchecked) with SomeMix

请注意,它仍然未被选中,并且在运行时仅测试匹配对象是SomeMix的实例;如果您更改为例如

def process(t: Any) = ...

您会得到不好的结果。