Я работаю с правильным синтаксисом и структурой для следующей проблемы.
У меня есть два набора данных с двумя отдельными схемами - назовите их ClientEvent
и ServerEvent
- хранящихся на диске. Кодовая база, над которой я работаю, определила класс, Reader[T :< Asset]
, где ClientEvent
и ServerEvent
- это подтипы Asset
. Asset
это черта.
Я пишу функцию:
def getPathAndReader(config): (String, Reader[Asset]) = {
if (config.readClient) {
return getClientPathAndReader(config)
} else {
return getServerPathAndReader(config)
}
}
Это не компилируется в моем коде Scala. Насколько я понимаю, T
должен быть подтипом Asset
, который как ServerEvent
, так и ClientEvent
, следовательно, Reader[ServerEvent] <: Reader[Asset]
. Но поскольку функции являются ковариантными в своих входных данных, функция, которую я написал, не может просто возвращать этот более низкий тип, я должен был бы привести его к супертипу? Это теряет слишком много информации?
load
- функция на признаке Asset
trait Reader[T <: Asset] {
def load(raw: DataFrame): Dataset[T]
}
Каким был бы альтернативный способ структурировать этот код?
Цель кода - взять возвращенный путь к файлу и вызвать Reader::load(filePath: String)
, чтобы получить данные обратно. Читатели с подтипами имеют некоторую внутреннюю логику для очистки данных, которые он извлекает с диска, прежде чем они будут возвращены как Dataframe
. Это означает, что он опирается на тип, который он передает. Я пришел из C ++ / C # фона, поэтому я думаю, что если у вас есть общий Reader[Asset]
, но вызовите Reader::load(path: String)
, он будет знать, что делать, основываясь на типе, который он на самом деле аналогично Base* ptr
и вызывает производный метод.