Scala具有一个很好的功能,可以推断模式匹配内的类型参数。它还检查模式匹配的穷举性。例如:
sealed trait PField[T]
case object PField1 extends PField[String]
case object PField2 extends PField[Int]
def getValue[X](f: PField[X]): X = f match {
case PField1 => "aaa"
case PField2 => 123
}
是否可以实现相同的功能,但使用类型成员而不是类型参数?
sealed trait Field {
type T
}
case object Field1 extends Field {
type T = String
}
case object Field2 extends Field {
type T = Int
}
以下解决方案不起作用(在Scala 2.12.6中测试):
//No exhaustiveness check
def getValue[X](f: Field {type T = X}): X = f match {
case Field1 => "aaa"
// case Field2 => 123
}
//casting needed
def getValue2[X](f: Field {type T = X}): X = (f: Field) match {
case Field1 => "aaa".asInstanceOf[X]
case Field2 => 123.asInstanceOf[X]
}
type Generified[X] = Field {type T = X}
//No exhaustiveness check
def getValue3[X](f: Generified[X]): X = f match {
case Field1 => "aaa"
// case Field2 => 123
}
在我的情况下,类型参数确实存在问题,因为我有许多字段子层次结构,并且每个层次结构都有一些类型类。我不能将所有需要的依赖项放在case对象的内部,因为它们以瘦JAR格式导出到客户端。
最佳答案
此解决方案是@Andrey Tyukin发布的解决方案的简化版本。
他说
这意味着,要进行详尽的模式匹配,必须忽略类型成员。因此,为了同时具有穷举性和类型推断性,我们需要使用类型参数进行密封的层次结构。
他建议创建案例类和模式匹配的单独层次结构,而不是在主层次结构上进行模式匹配。但是,就我而言,它可以简化:我使用类型参数创建了新的密封特征,但相同的案例对象用于模式匹配(“唯一保证”保留在对象本身中)。这是最终的解决方案:
sealed trait Field {
type T
def ug: TField[T]
}
sealed trait TField[G] extends Field {
type T = G
def ug: TField[T] = this
}
case object Field1 extends TField[String]
case object Field2 extends TField[Int]
def getValue[X](f: Field {type T = X}): X = (f.ug: TField[X]) match {
case Field1 => "abc"
case Field2 => 123
}
因此,我可以使用
Field
特性来定义类型类,而无需进入更高种类的类型,而可以切换到TField[G]
进行模式匹配。关于scala - 具有类型成员的案例对象的模式匹配,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51766569/