私のコントロールの外のどこかにpayload
ジェネリック変数を定義するレガシーJavaコードがあります(つまり、その型を変更することはできません):
// Java code
Wrapper<? extends SomeBaseType> payload = ...
コードでメソッドパラメーターなどの値を受け取りpayload
、それをScalaに渡したいcase class
(アクターシステムでメッセージとして使用するため)が、少なくともコンパイラー警告が表示されないように定義を正しく取得しない。
// still Java code
ScalaMessage msg = new ScalaMessage(payload);
これにより、コンパイラに「型安全性:コンストラクタ...はraw型に属します...」という警告が表示されます。
Scalacase class
は次のように定義されます。
// Scala code
case class ScalaMessage[T <: SomeBaseType](payload: Wrapper[T])
コードがきれいにコンパイルされるようにケースクラスを定義するにはどうすればよいですか?(残念ながら、JavaWrapper
クラスのコードやpayload
パラメーターのタイプを変更することはできません)
ペイロードパラメータの起源を明確にするために更新されました
追加payload
比較のために、Javaでは、変数が定義されているのとまったく同じ方法でパラメーターを定義できます。
// Java code
void doSomethingWith(Wrapper<? extends SomeBaseType> payload) {}
それに応じてそれを呼び出す
// Java code
doSomethingWith(payload)
ただし、「raw型」の警告が表示されない限り、たとえばWrapperオブジェクトを直接インスタンス化することはできません。ここでは、static
ヘルパーメソッドを使用する必要があります。
static <T> Wrapper<T> of(T value) {
return new Wrapper<T>(value);
}
この静的ヘルパーを使用して、Wrapper
オブジェクトをインスタンス化します。
// Java code
MyDerivedType value = ... // constructed elsewhere, actual type is not known!
Wrapper<? extends SomeBaseType> payload = Wrapper.of(value);
解決
同様のヘルパーメソッドをScalaコンパニオンオブジェクトに追加できます。
// Scala code
object ScalaMessageHelper {
def apply[T <: SomeBaseType](payload: Wrapper[T]) =
new ScalaMessage(payload)
}
object ScalaMessageHelper2 {
def apply[T <: SomeBaseType](payload: Wrapper[T]) =
ScalaMessage(payload) // uses implicit apply() method of case class
}
Javaからこれを使用して、ScalaMessage
問題のないクラスをインスタンス化します。
// Java code
ScalaMessage msg = ScalaMessageHelper.apply(payload);
誰かがよりエレガントな解決策を思い付かない限り、私はこれを答えとして抽出します...
ありがとうございました!