SilentICE
SilentICE

Reputation: 700

Scala data structure with type safe accessors

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

Answers (1)

Paolo
Paolo

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

Related Questions