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