Reputation: 700
Please note I am learning Scala so what I suggest may not be the best (idomatic) way of achieving this, therefore I'll describe the problem I'm trying to solve first, then my current implementation!
Problem: Given some input document, e.g. xml or json, create an object Doc
with its raw contents as a variable, apply a sequence of FieldExtractors
which extract a number of value, i.e. Fields
, which are stored on the Doc
object and can be accessed in a type safe manner later, e.g. val username: String = doc.getField(UsernameField)
N.B everything must be Serializable so it can be passed over the wire via a particular framework
So, my current attempt:
abstract class Field[+T <: Serializable](val name: String, val valueType: Class[T])
trait Fields {
var fields: mutable.HashMap[Class[Field[Serializable]], Field[Serializable]] = mutable.HashMap()
def hasField[T <: Serializable](field: Field[T]): Boolean = false
def getField[T <: Serializable](field: Field[T]): T = fields.get(field).asInstanceOf(T)
def setField[T <: Serializable](field: Field[T], value: T): Unit = fields.put(field, value)
}
class Doc(val rawData: String) with Fields
abstract class FieldExtractor[+TYPE <: Serializable](val field: Field[TYPE]) {
def extractField(input: Doc): Option[TYPE]
}
But I get all sorts of errors such as:
Error:(14, 39) inferred type arguments [String] do not conform to method hasField's type parameter bounds [T <: Serializable] val result:Boolean = fieldsObject.hasField(field) ^
I'm wondering if maybe I should use Value types instead? Or the https://github.com/mikaelv/strucs project (which seems rather young)? Or whether there's a better approach?
Eventually I'd write something like
extractors.foldLeft(doc)((doc, extractor) => doc.setField(field, extractor.extractField(doc); doc
Upvotes: 2
Views: 196
Reputation: 22638
This appears to be a symptom of Scala having its own Serializable
class.
String
(which Scala uses as a synonym for java.lang.String
) implements Java's java.io.Serializable
whereas your Field
class has declared the generic bounds using Scala's Serializable
class.
If you change the declaration to this:
abstract class Field[+T <: java.io.Serializable](val name: String, val valueType: Class[T])
it compiles* and does the type safe get/set checks correctly for me (* using Scala SDK 2.11.7, I had to correct some minor typos).
Note, there's also an error in the Fields
class. I think you meant to declare the hash map as:
fields: mutable.HashMap[Field[Serializable], Serializable]
Upvotes: 3