如何将工厂方法添加到Scala中的现有Java类

Leo*_*Leo 9 java scala implicits

在纯Scala环境中,如果我想将工厂方法"添加"到现有对象,我可以执行以下操作:

object Test

object Extensions {

    object RichTest {
        def someFactory = new Test()
    }
    implicit def fromTest(t: Test.type) = RichTest

}

...

import Extensions._
val t = Test.someFactory
Run Code Online (Sandbox Code Playgroud)

我需要将这样的功能与现有的Java类结合使用.在我的具体的例子,我想一个工厂方法添加fromLocation到类com.google.android.maps.GeoPoint(和我想每一个Android开发者就会知道为什么这将是有益的;-)).

但是,如果我尝试做类似的事情

implicit def fromGeoPoint(t: GeoPoint.type) = RichTest
Run Code Online (Sandbox Code Playgroud)

我收到一个错误说明

类型不匹配; 发现:com.google.android.maps.GeoPoint.type(底层类型对象为com.google.android.maps.GeoPoint)必需:AnyRef

所以我想知道是否有任何方式可以实现上述方法 - 或者提供隐式转换Location是否GeoPoint是Scala中的首选方式,因此Location可以在GeoPoint需要时使用?


根据评论中的要求,使用场景:

// 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, ...)
    ....
}
Run Code Online (Sandbox Code Playgroud)

但是,请记住,这只是一般问题的一个具体示例;-)

Vla*_*dim 2

从 Scala 版本 2.9.1 开始,无法使用工厂方法扩展 Java 类。

但是,还有三种替代解决方案:

  1. 编写Scala 编译器插件来适应所需的更改,然后扩展 Java 类。
  2. 创建一个独立的工厂方法。
  3. 避免完全使用工厂方法并添加隐式转换,以便始终可以使用 Location 对象来代替 GeoPoint。

就我个人而言,如果我经常使用Location->或任何其他转换,我会选择第三个选项,特别是在转换始终可以无异常且类接口不重叠的情况下。GeoPoint

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, ...)
}
Run Code Online (Sandbox Code Playgroud)