I'm trying to figure out a way to get away from overloaded methods. Currently I'm using this approach to provide nice APIs to the user:
def get(id: String): Option[JsonDocument]
def get(id: String, timeout: Duration): Option[JsonDocument]
def get[D <: Document[_]](id: String, target: Class[D]): Option[D]
def get[D <: Document[_]](id: String, target: Class[D], timeout: Duration): Option[D]
Now since scala has default parameters I want to condense this into one method. But because D is generic, I need the default if not provided not to be "Nothing", but rather "JsonDocument".
My current approach does this:
def get[D <: Document[_]](id: String, target: Class[D] = classOf[JsonDocument], timeout: Duration = null): Option[D]
And as it turns out the compiler is super happy with it, but the IDE has problems. if the target is not explicitly provided (like with target = JsonDocument or any other) it thinks the return type is Option[Nothing] and therefore its confusing to the user.
So my question is: with these types, is it possible to provide a "default" type of JsonDocument for type D if it is not provided by the user to be overridden?
There is an solution to the default generic parameters problem given at http://www.cakesolutions.net/teamblogs/default-type-parameters-with-implicits-in-scala. Applying to your case, you'd get something like (untested):
trait DefaultsTo[Type, Default]
object DefaultsTo {
implicit def defaultDefaultsTo[T]: DefaultsTo[T, T] = null
implicit def fallback[T, D]: DefaultsTo[T, D] = null
}
// use target.runtimeClass in the implementation
def get[D <: Document[_]](id: String, timeout: Duration)(implicit target: scala.reflect.ClassTag[D], default: DefaultsTo[D, JsonDocument]): Option[D]
To use: get(id, timeout) for JsonDocument or get[OtherDocument](id, timeout). Of course, whether the IDE (IntelliJ?) is going to infer the type correctly is a different question!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With