Scala中返回类型的分派

Scala中返回类型的分派,scala,Scala,假设我有以下案例类: case class Category(name: String) case class Record(price: Double, description: String, category: Category) case class Sale(price: Double, qty: Int, dateOfSale: Date, category: Category) 我想调用一个方法,根据类别返回Sale或Record列表。唯一的区别是返回类型。因此,我想要的不是

假设我有以下案例类:

case class Category(name: String)

case class Record(price: Double, description: String, category: Category)

case class Sale(price: Double, qty: Int, dateOfSale: Date, category: Category)
我想调用一个方法,根据类别返回
Sale
Record
列表。唯一的区别是返回类型。因此,我想要的不是
findSalesByCategory
findRecordsByCategory
,而是:

def findByCategory[T](category: Category): List[T] = classOf[T] match {
  case c if c == classOf[Sale]   => findRecordsByCategory(category)
  case c if c == classOf[Record] => findSalesByCategory(category)
}
显然,这在以下情况下会失败:

error: class type required but T found
    def findByCategory[T](category: Category): List[T] = classOf[T] match {
                                                    ^
有没有可行的方法?

您可以使用类型标签:

import scala.reflect.runtime.universe._

def findByCategory[T: TypeTag](category: Category): List[T] = {

   typeOf[T] match {
       case t if t =:= typeOf[Sale]   => findSalesByCategory(category)
       case t if t =:= typeOf[Record] => findRecordsByCategory(category)
   }
}

由于您的类别不是通用的,
ClassTag
也可以满足以下要求:

import scala.reflect.{ClassTag, classTag}

def findByCategory[T: ClassTag](category: Category): List[T] = {
  classTag[T] match {
    case c if c == classTag[Sale] => findSalesByCategory(category)
    case c if c == classTag[Record] => findRecordByCategory(category)
  }
}
当您要匹配的
T
的子类型未参数化时,这将起作用;在这种情况下,您必须使用
TypeTag
s

有一种方法可以稍微简化匹配。您可以将
ClassTag
s或
Class
es保存到
val
中,并在其上进行匹配:

import scala.reflect.{ClassTag, classTag}

val saleClass = classOf[Sale]
val recordClass = classOf[Record]
def findByCategory[T: ClassTag](category: Category): List[T] = {
  classTag[T].runtimeClass match {
    case `saleClass` => findSalesByCategory(category)
    case `recordClass` => findRecordByCategory(category)
  }
}

它不起作用-
TypeTag#tpe
返回
Type
的实例,但是
classOf
返回
Class[\u]
,它们是不同的。您可以在Scala REPL中轻松地检查它。您可能还应该编写
typeOf[Sale]
,而不是
typeOf(Sale)
——它是一个类型参数。@Vladimitavevev yes。我在我的编辑器里是正确的,在这里输入错误。谢谢。您可以发布
findSalesByCategory
findRecordsByCategory
的声明吗?显然的
def findRecordsByCategory(c:Category):List[Record]=??
def findSalesByCategory(c:Category):List[Sale]=??
似乎没有编译。这是类型类的一个很好的用例。