17

私はScalaクラスを持っています:

class Foo(val x:String = "default X", val y:String = "default Y" ) 

Javaから呼び出したいのですが、デフォルトのパラメータを使用しています

合格nullは機能しません(null期待どおりに割り当てられます)

new Foo(null,null); //both are instantiated as null

このトリックは私にとってはうまくいきましたが、それは醜いです、そして私はもっと良い方法があるかどうか疑問に思います:

Scala

class Foo(val x:String = "default X", val y:String = "default Y" ) {
  def this(x:Object) = this()
}

Java

new Foo(null); //no matter what I pass it should work

ただし、コンストラクターのオーバーロードのトリックを取り除き、0パラメーターコンストラクターを使用したいと思います

それは可能ですか?

4

3 に答える 3

7

そのような方法はないようです:https ://issues.scala-lang.org/browse/SI-4278

問題:すべてオプションの引数を持つクラスに対して、デフォルトの引数なしコンストラクターを生成する必要があります
...

Lukas Rytz:言語の統一性に関して、これは修正しないことにしました。これはフレームワークとの相互運用性の問題であるため、言語レベルで修正するべきではないと考えています。

回避策:デフォルトを繰り返すか、1つを抽象化するか、1つのデフォルトを引数なしのコンストラクターに入れます

次に、Lukasはあなたが見つけたのと同じ解決策を提案します:

class C(a: A = aDefault, b: B = C.bDefault) {
  def this() { this(b = C.bDefault) }
}
object C { def bDefault = ... }

// OR

class C(a: A = aDefault, b: B) {
  def this() { this(b = bDefault) }
}
于 2012-10-25T00:20:52.063 に答える
3

解決策があります。記事の「デフォルトの引数」のセクションを確認してください:https ://lampwww.epfl.ch/~michelou/scala/using-scala-from-java.html

。$default$ [number]形式を使用して、Javaから適切な位置引数を渡すことにより、コンストラクターとメソッドの両方を呼び出すことができます。

ここでのスコープは次のとおりです。

  • クラスコンストラクター:<<ClassName>>。init$default $ 1(最初の引数の値)コンストラクター定義で設定されたデフォルト値default $ 2(2番目の引数のデフォルト値)など。
  • メソッド呼び出し:object.methodName $ default $ 1は、メソッドシグネチャなどで割り当てられたメソッドの最初のパラメーターのデフォルト値を解決します。

例:

import za.co.absa.spline.core.SparkLineageInitializer;
SparkLineageInitializer.SparkSessionWrapper lineage = SparkLineageInitializer.SparkSessionWrapper(spark);
lineage.enableLineageTracking(lineage.enableLineageTracking$default$1());

この例では、Mavenの依存関係は次のとおりです。groupId:za.co.absa.spline ArtifactId:スプラインコアバージョン:0.3.1

于 2018-10-18T21:24:30.383 に答える
2

より一般的には、デフォルトの引数を持つScalaクラスがあり、すべてを指定せずにデフォルトの0、1、またはそれ以上をオーバーライドするJavaでインスタンス化する場合は、ScalaAPIを拡張してコンパニオンオブジェクトにBuilderを含めることを検討してください。

case class Foo(
  a: String = "a",
  b: String = "b",
  c: String = "c"
)

object Foo {
  class Builder {
    var a: String = "a"
    var b: String = "b"
    var c: String = "c"
    def withA(x: String) = { a = x; this }
    def withB(x: String) = { b = x; this }
    def withC(x: String) = { c = x; this }
    def build = Foo(a, b, c)
  }
}

public class App {
    public static void main(String[] args) {
        Foo f = new Foo.Builder()
            .withA("override a")
            .build();
    }
}
于 2017-02-18T01:51:18.270 に答える