Scala - доступ к типу параметризованного класса

Представьте, что у меня есть Коробка, в которой можно держать животных какого-то типа.
В эту коробку могут быть помещены необработанные данные, которые следует преобразовать / сериализовать в животных того же типа, что и те, которые уже есть в коробке.
Другими словами, если Коробке собак даны некоторые "данные", я хочу подтвердить, что "данными" является другая собака.

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].
Если я позволю этому быть как есть:

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

Я получаю ошибку компиляции, говорящую, что у меня нет неявного для типа T (даже несмотря на то, что у меня есть все возможные последствия для под-черт Animal).
Похоже, я не могу сказать компилятору, что я хочу проверить данные по типу Animal, который содержится в текущем Box.

  1. Почему это происходит?
  2. Можно ли это решить и как?

1 ответ

Решение

Вы должны перенести неявное значение из call-сайта, на котором 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, может быть каким-то макро-сгенерированным токеном, который обеспечивает некоторую стратегию десериализации.

Другие вопросы по тегам