2

Eclipse データバインディングのコンテキストでは、オブジェクトのファクトリとして機能する Java クラスがかなりありIObservableます。たとえばBeanObservablesPojoObservablesEMFObservables、 などがあり、それらはすべて次のような一連のメソッドを実装しています。

  public static IObservableValue observeValue(Object target, String property)

Scala の世界にいた場合、これらのファクトリのそれぞれは、たとえば などの共通のトレイトを実装するシングルトン オブジェクトになるでしょう。IObservableFactoryたとえば、データ バインディングを作成するためにそれらを使用するメソッドに暗黙的な値としてそれらを渡すことができます。 .

しかし、それらはJavaで定義されているため、私にはそれができないようです。書けない

val pojoObservableFact = PojoObservables

PojoObservablesは値として認識されないためです。

PojoObservablesコンパイラが Scala のクラスに対応するシングルトンを「インスタンス化」する方法はありますか? またはそれに対する回避策はありますか?自分でシングルトンを作成してすべてのメソッド呼び出しを転送できることはわかっていますが、これは少し面倒に思えます。


編集

わかりやすくするために、これが私がやろうとしていることです: 渡されたファクトリを使用して監視可能な値を作成するメソッドを定義します。

def createObservable(fact: ObservableFactory, target: AnyRef, property: String) =
  fact.observeValue(target, property)

しかし、静的メソッドのみを持つJavaクラスをこのメソッドに定義するObservableFactory方法や実際に渡す方法はわかりません。PojoObservablescreateObservable

4

4 に答える 4

4

他の誰も有効な答えを思いつかない場合、メソッド シグネチャに基づいてコード ジェネレーターを作成するのはそれほど難しいことではないと思います。

val a = classOf[String].getMethods.map(_.toString).filter(s =>
  s.contains("public") && s.contains("static")
)

Stringたとえば、すべてのメソッド シグネチャ (この場合は for) を文字列として引き出します。それで

val b = a.map(_.split(" ").reverse.take(2).reverse)

戻り値の型が前に分割された関数シグネチャのみを取得します。今

val c = b.map(_(1).dropWhile(_ != '(').drop(1).takeWhile(_ != ')').split(","))
val d = b.map(_(1).takeWhile(_ != '('))

引数のシグネチャと関数の名前をそれぞれ取得します。次に、プリミティブ型を変換する必要があります。これは、最初の文字を大文字にするだけでよいため、非常に簡単です (ユニットになる void を保存します)。

def jprim2scala(s: String) = {
  val prim = List("boolean","byte","short","char","int","long","float","double")
  def arrayconvert(s: String): String = {
    if (s.endsWith("[]")) "Array["+arrayconvert(s.substring(0,s.length-2))+"]"
    else if (s=="void") "Unit"
    else if (prim contains s) {
      s.substring(0,1).toUpperCase + s.substring(1)
    }
    else s
  }
  arrayconvert(s)
}

def e = (b,c).zipped.map((bi,ci) => (jprim2scala(bi(0)), ci.map(jprim2scala)))

最後に、すべてを元に戻すことができます。

val f = (d,e).zipped.map((name,ei) => {
  val (ret,args) = ei
  val lastname = name.split('.').last
  "def "+lastname+"(" +
  (for ((a,i) <- args.zipWithIndex) yield ("a"+i+": "+a)).mkString(", ") +
  "): "+ret+" = "+name+"("+(0 until args.length).map("a"+_).mkString(",")+")"
})

これで、適切なシングルトンに (手動で) 配置できる Scala コードの束ができました。

object Stringleton {
  // The contents of this is cut-and-paste f.map("  "+_).foreach(println)
  def valueOf(a0: java.lang.Object): java.lang.String = java.lang.String.valueOf(a0)
  def valueOf(a0: Array[Char]): java.lang.String = java.lang.String.valueOf(a0)
  def valueOf(a0: Array[Char], a1: Int, a2: Int): java.lang.String = java.lang.String.valueOf(a0,a1,a2)
  def valueOf(a0: Boolean): java.lang.String = java.lang.String.valueOf(a0)
  def valueOf(a0: Char): java.lang.String = java.lang.String.valueOf(a0)
  def valueOf(a0: Int): java.lang.String = java.lang.String.valueOf(a0)
  def valueOf(a0: Long): java.lang.String = java.lang.String.valueOf(a0)
  def valueOf(a0: Float): java.lang.String = java.lang.String.valueOf(a0)
  def valueOf(a0: Double): java.lang.String = java.lang.String.valueOf(a0)
  def copyValueOf(a0: Array[Char], a1: Int, a2: Int): java.lang.String = java.lang.String.copyValueOf(a0,a1,a2)
  def copyValueOf(a0: Array[Char]): java.lang.String = java.lang.String.copyValueOf(a0)
  def format(a0: java.lang.String, a1: Array[java.lang.Object]): java.lang.String = java.lang.String.format(a0,a1)
  def format(a0: java.util.Locale, a1: java.lang.String, a2: Array[java.lang.Object]): java.lang.String = java.lang.String.format(a0,a1,a2)
}

(ちなみに、Varargs はここでは機能しません。存在する場合は修正する必要があります。.isVarArgsメソッド自体 (文字列表現ではない) からメソッドに戻り、最後の Array[X ] を X* に変換し、それを として呼び出しますai: _*。)

このアプローチの良いところは、一般的なメソッドがある場合、それらを引き出すために構造型付けを使用する必要さえないことです。ラップされたメソッドが継承する独自のトレイトを定義できます! (そして、あなたが特に野心的であれば、ほぼ一致するが完全には一致しないメソッドを、実際に一致するように押し込むことができます。たとえば、すべてが同じメソッド名を持つようにすることができます。)

于 2011-02-07T13:32:00.167 に答える
3

ファクトリメソッド(または必要に応じて一連のメソッド)を単純に渡してみませんか?

def createObservable(fact: (AnyRef, String) => IObservableValue, 
target: AnyRef, property: String) = fact(target, property)

createObservable(BeanObservables.createObservable, target, property)
于 2011-02-07T13:13:19.570 に答える
0

したがって、ここPojoObservablesからの参照をとると、あなたが説明しているように静的メソッドを見ることができます。observeValue

これは簡単な方法です。ScalaはJavaクラスの静的メソッドをコンパニオンで定義されているかのように扱います。これは、昔ながらのJavaであるかのように使用できます。

import org.eclipse.core.databinding.beans.PojoObservables
...
val ov = PojoObservables.observeValue(target, property)

または、静的インポートを使用した新しい学校のバリアント:

import org.eclipse.core.databinding.beans.PojoObservables._
...
val ov = observeValue(target, property)

その後、そのようなメソッドを関数オブジェクトとして渡すことができます。関数が何らかの形でそのインターフェースによってエスコートされる必要があるという考えは、非常にJava中心の考え方であり、必要なものをすべて参照し、他のより種類の多い関数への引数として提供するだけです:)

于 2011-02-07T12:52:12.660 に答える
-1

1 つの方法は、リフレクションを使用することです。

object PojoObservables

val pojoObservableFact = PojoObservables.getClass.getConstructor()
pojoObservableFact.setAccessible(true)
pojoObservableFact.newInstance()

これで、PojoObservables.method でメソッドを呼び出すことができます...

于 2011-02-07T12:36:50.637 に答える