Trying to implement a Java interface

53 views
Skip to first unread message

Sébastien Lorion

unread,
Jul 3, 2014, 2:18:57 AM7/3/14
to scala...@googlegroups.com
Hello,

I am trying to implement the interface https://github.com/aaberg/sql2o/blob/master/core/src/main/java/org/sql2o/converters/Converter.java for Option[T] but I cannot figure out how to do it as I keep getting compiler type errors. Below is my best attempt (I am quite new at Scala). When I compile it, it gives me the error:

"Error:(29, 37) type mismatch;
 found   : x.type (with underlying type T)
 required: ?0
 valueConverter.toDatabaseParam(x)"


package foo.bar

import org.sql2o.converters.{Convert, Converter, ConverterException}

class OptionConverter[T] extends Converter[Option[T]] {
  override def convert(value: Any): Option[T] = {
    value match {
      case null | None => None
      case _ =>
        val valueConverter = Convert.getConverterIfExists(value.getClass)

        if (valueConverter == null)
          throw new ConverterException(s"Cannot find a converter for type ${value.getClass.toString}.")
        else
          Option(valueConverter.convert(value).asInstanceOf[T])
    }
  }

  override def toDatabaseParam(value: Option[T]): AnyRef =
  {
    value match {
      case None => null
      case Some(x) =>
        val valueConverter = Convert.getConverterIfExists(x.getClass)

        if (valueConverter == null)
          throw new ConverterException(s"Cannot find a converter for type ${x.getClass.toString}.")
        else
          valueConverter.toDatabaseParam(x) // compiler error here, for x
    }
  }
}

that class is then meant to be used like this:

private[this] lazy val customQuirks = new PostgresQuirks() {
  {
    converters.put(classOf[Option[java.lang.Integer]], new OptionConverter[java.lang.Integer])
    converters.put(classOf[Option[scala.Int]], new OptionConverter[scala.Int])
    // ...
  }
}

Sonnenschein

unread,
Jul 3, 2014, 7:18:13 AM7/3/14
to scala...@googlegroups.com
Hi Sébastien:

First, here is the boiled down code demonstraiting your question (please concider always supplying self-contained code otherwise you'll probably get no response):

trait Converter[T] {
  def toDatabaseParam(value: T): Object

}
class OptionConverter[T] extends Converter[Option[T]] {
  override def toDatabaseParam(value: Option[T]): AnyRef =
    value map { x =>
      // Convert.java:
public static Converter getConverter(Class clazz)
      def valueConverterRaw: Converter[_] = ???
      valueConverterRaw.toDatabaseParam(x) // error
     
      def valueConverter: Converter[T] = ???
      valueConverter.toDatabaseParam(x)
   }
}

The issue is that toDatabaseParam returns a raw type that is always a sign of suboptimal design. To get rid of it you could cast by asInstanceOf respectively add something like

valueConverterRaw match {
  case c: Converter[T] => c.toDatabaseParam(x)
  case _ => ???
}


Peter

Sébastien Lorion

unread,
Jul 3, 2014, 11:53:14 PM7/3/14
to scala...@googlegroups.com
Thank you Peter, that did the trick. I think it can even be simplified to this:

override def toDatabaseParam(value: Option[T]): AnyRef = {
  value match {
    case None => null
    case Some(x) =>
      val valueConverter: Converter[T] = Convert.getConverterIfExists(x.getClass)

      if (valueConverter == null)
        throw new ConverterException(s"Cannot find a converter for type ${x.getClass.toString}.")
      else
        valueConverter.toDatabaseParam(x)
  }
}

That said, I do not understand why the compiler cannot infer that valueConverter is a Converter[T] without me telling it explicitly.

Sébastien
Reply all
Reply to author
Forward
0 new messages