In a pure Scala environment, I could do the following if I wanted to "add" a factory method to an existing object:
object Test
object Extensions {
object RichTest {
def someFactory = new Test()
}
implicit def fromTest(t: Test.type) = RichTest
}
...
import Extensions._
val t = Test.someFactory
I would need such a functionality in combination with an existing Java class. In my concrete example, I would like to add a factory method fromLocation
to the class com.google.android.maps.GeoPoint
(and I guess every Android developer will know why this would be useful ;-) ).
However, if I try to do something like
implicit def fromGeoPoint(t: GeoPoint.type) = RichTest
I get an error stating
type mismatch; found : com.google.android.maps.GeoPoint.type (with underlying type object com.google.android.maps.GeoPoint) required: AnyRef
So I wonder if there is any way how the above approach could be implemented - or would providing an implicit conversion from Location
to GeoPoint
be the preferred way in Scala so a Location
could be used whenever a GeoPoint
is required?
As requested in the comments, a usage scenario:
// Callback you get from the GPS
override def onLocationChanged(l: Location) {
// You want to put a marker on a map, hence a GeoPoint is required
val gp: GeoPoint = GeoPoint.fromLocation(location)
val item = new OverlayItem(gp, ...)
....
}
However, keep in mind that this is just one specific example for the general problem ;-)
As of Scala version 2.9.1 it is not possible to extend Java class with a factory method.
However, there are three alternative solutions:
Personally I'd go for the third option if I used Location
-> GeoPoint
or any other conversion a lot of the time, especially in the scenario when conversion can always be done without exceptions and class interfaces don't overlap.
implicit def geoPointFromLocation(l: Location):GeoPoint = new GeoPoint...
override def onLocationChanged(l: Location) {
val gp: GeoPoint = l // let Scala compiler do the conversion for you
val item = new OverlayItem(gp, ...)
....
// or just pass the location to OverlayItem constructor directly
val item2 = new OverlayItem(l, ...)
}