4

以下は、http: //www.tikalk.com/java/blog/type-safe-builder-scala-using-type-constraintsで説明されている、Scalaのタイプセーフで流動的なビルダーパターンです。これは、ScalaおよびJava用のビルダーライブラリに似ていますが、特にコンパイル時のビルダーチェックを扱います。これはJavaからどのように呼び出すことができますか?「scala.Predef$$eq $ Colon $ eq」パラメーターを指定して、ScalaおよびJava用のクリーンなAPIを使用して実行できますか?

sealed trait TBoolean
sealed trait TTrue extends TBoolean
sealed trait TFalse extends TBoolean

class Builder[HasProperty <: TBoolean] private(i: Int) {
  protected def this() = this(-1)
  def withProperty(i: Int)(implicit ev: HasProperty =:= TFalse) = new Builder[TTrue](i)
  def build(implicit ev: HasProperty =:= TTrue) = println(i)
}

//javap output
    public class Builder extends java.lang.Object implements scala.ScalaObject{
    public Builder withProperty(int, scala.Predef$$eq$colon$eq); //How is this called from Java?
    public void build(scala.Predef$$eq$colon$eq);
    public Builder();
}
object Builder {
  def apply() = new Builder[TFalse]
}
4

2 に答える 2

6

この API は Java から使用できるはずですが、Scala バージョンに比べて多少ノイズが多くなります。いくつかの便利なフィールドは、物事を少し静かにします:

object Builder {
   def apply() = new Builder[TFalse]
   val unassigned = =:=.tpEquals[TFalse]
   val assigned = =:=.tpEquals[TTrue] 
}

Java クライアント コードは最終的に次のようになります。

Builder$.MODULE$.apply()
   .withProperty(10, Builder$.MODULE$.unassigned())
   .build(Builder$.MODULE$.assigned());

このbuildメソッドは、すべてのプロパティが割り当てられていることを確認する必要があるため、複数のプロパティに一般化するとかなりノイズが多くなります。

Builder$.MODULE$.apply()
   .withProp1(10, Builder$.MODULE$.unassigned())
   .withProp2(20, Builder$.MODULE$.unassigned())
   .withProp3(30, Builder$.MODULE$.unassigned())
   // ...
   .build(Builder$.MODULE$.assigned(), 
          Builder$.MODULE$.assigned(), 
          Builder$.MODULE$.assigned(), 
          //...
         );

ヘルパー クラスのいくつかの静的デリゲート (およびいくつかの静的インポート) を使用すると、これを次のようにまとめることができるはずです。

createBuilder()
   .withProp1(10, unassigned())
   .withProp2(20, unassigned())
   .build(assigned(), assigned());
于 2011-06-14T21:35:02.050 に答える
3

わかりました、Aaron と ittayd に感謝します...これは、Scala と Java 用の流動的な API を備えたビルダーです。

import annotation.bridge

sealed trait TBoolean
sealed trait TTrue extends TBoolean
sealed trait TFalse extends TBoolean

class Builder[HasProperty <: TBoolean] private(i: Int) {
  protected def this() = this(-1)

  def withProperty(i: Int)(implicit ev: HasProperty =:= TFalse) = new Builder[TTrue](i)
  def build(implicit ev: HasProperty =:= TTrue):Int = i
  @bridge def withProperty(i: Int) = new Builder[TTrue](i)
  @bridge def build = build(null)
}

object Builder {
  def apply() = new Builder[TFalse]
  val unassigned = =:=.tpEquals[TFalse]
  val assigned = =:=.tpEquals[TTrue]
}

Scala の使用法 (タイプ セーフ):

val v = Builder().withProperty(2).build

Java の使用法 I (型は安全ですが、醜い):

int i = Builder$.MODULE$.apply()
        .withProperty(5, Builder$.MODULE$.unassigned())
         .build(Builder$.MODULE$.assigned()); 

Java 使用法 II (タイプ セーフではありませんが、@Bridge 呼び出しを使用してよりクリーンにします):

static Builder createBuilder() {
  return Builder$.MODULE$.apply();
}
...
int j = createBuilder().withProperty(7).build();
于 2011-06-16T22:02:52.893 に答える