1

想象一下,我有一个可以容纳某种动物的盒子。
可以给这个盒子提供原始数据,这些数据应该被转换/序列化成与盒子里已经存在的动物相同类型的动物。
换句话说,如果给一盒狗一些“数据”,我想验证“数据”是另一只狗。

trait Animal
trait Dog extends Animal
trait Cat extends Animal   

 class Box[T<:Animal](elems: List[T]) {

      def receiveNewAnimal(data: String): T = validate[T](data)(<implicit val>)
    }

通常,当我想针对特定动物验证“rawData”时,我会这样做(例如狗):

val getMyDog(data: String): Dog = validate[Dog](data)

但是,我不知道 Box[T] 拥有哪种类型的 Animal。
如果我让它保持原样:

def receiveNewAnimal(data: String): T = validate[T](data)(<implicit val>)

我收到一个编译错误,说我没有 T 类型的隐式(即使很难,我也拥有 Animal 的子特征的所有可能的隐式)。
看来我无法告诉编译器,我想根据当前 Box 包含的 Animal 类型验证数据。

  1. 为什么会这样?
  2. 可以解决吗?如何解决?
4

1 回答 1

1

Box您必须将隐式值从调用构造函数的调用站点传输到validate方法。


假设有类似下面的类型类:

trait Validatable[T]

validate需要:T_Validatable

def validate[T : Validatable](serializedData: String): T = ???

你可以这样做:

trait Animal
trait Dog extends Animal
trait Cat extends Animal   

class Box[T <: Animal : Validatable](elems: List[T]) {
  def receiveNewAnimal(data: String): T = validate[T](data)
}

或者,如果你validate用第二个参数列表声明,你可以对Box:

def validate2[T](serializedData: String)(implicit v: Validatable[T]): T = ???

class Box2[T <: Animal](elems: List[T])(implicit v: Validatable[T]) {
  def receiveNewAnimal(data: String): T = validate[T](data)(v)
}

Validatable在这种情况下,实际上并不那么重要,可能是一些,ClassTag可能是一些提供反序列化策略的宏生成令牌。

于 2018-04-14T23:55:43.923 回答