これは明らかなことですが、私はまだエレガントな解決策を見つけていません。さまざまな理由から、不変のScalaマップ(Scala 2.10のscala.collection.immutable.Map)を作成する必要がありますが、作成できるのはJavaコードのみです。どうすればよいですか?
2 に答える
ワイルドな推測 - ここでは何もありません:
scala.collection.immutable.Map$.MODULE$.<…, …>empty()
最初は、次のことを行うだけで失敗することに戸惑いました。
scala.collection.immutable.Map<Integer, String> = scala.collection.immutable.Map$.<Integer, String>empty();
奇妙に思えた理由は、scala が内部的に逆参照MODULE$
して対応する (非静的) メソッドを呼び出す静的フォワーダーを生成するという事実を知っているからです。私はいくつかのテストを行いました.私が見つけたものは元の質問とは多少関係がありますが、それでも関連しており、知っておくとよいでしょう.
次があるとします。
package test
object MyScalaObject {
def empty[A, B]: Map[A, B] = sys.error("TODO")
}
を使用javap
すると、静的フォワーダーが生成されていることがわかります。
public class test.MyScalaObject extends java.lang.Object{
public static scala.collection.immutable.Map empty();
public test.MyScalaObject();
}
実際、Java では次のことを実行できます。
scala.collection.immutable.Map<Integer, String> myMap = test.MyScalaObject.<Integer, String>empty();
すべてが順調です。ただし、同じシグネチャを持つメソッドも定義するクラスまたはトレイトを追加するMyScalaObject
と、scala によって静的フォワーダーが生成されません (JVM ではクラスが同じシグネチャを持つ静的メソッドと非静的メソッドの両方を定義することを許可していないためです)。 )。おそらく、静的フォワーダーの生成を妨げる別の微妙な状況が他にもあるでしょう。
検討:
package test
class MyScalaObject {
def empty[A, B]: Map[A, B] = sys.error("TODO")
}
object MyScalaObject {
def empty[A, B]: Map[A, B] = sys.error("TODO TOO")
}
javap
静的フォワーダーが実際に消えたことを示しています。
public class test.MyScalaObject extends java.lang.Object{
public scala.collection.immutable.Map empty();
public test.MyScalaObject();
}
この場合$MODULE
、シングルトン オブジェクトの (一意の) インスタンスを指すものを明示的に逆参照する必要があることを意味します。
scala.collection.immutable.Map<Integer, String> myMap = test.MyScalaObject$.MODULE$.<Integer, String>empty();
結局のところ、トレイトscala.collection.immutable.Map
とそのコンパニオン オブジェクトの両方がパラメーターなしのempty
メソッドを定義しているため、まさにこの問題に遭遇します。
道徳的に言えば、静的フォワーダーは潜在的に有用な機能ですが、クラスを変更する (この場合empty
は class にメソッドを追加するMyScalaObject
) という事実だけで、そのコンパニオン オブジェクト自体に触れることなく機能を壊す可能性があるため、非常に壊れやすいということです。したがって、ライブラリの新しいバージョンに更新する際の破損の可能性を防ぐために、MODULE$
見た目が悪くても、静的フォワーダーが現在存在していても、(Wilfred Springer の回答のように)常に明示的に参照することをお勧めします。