ho qualche codice Java legacy che definisce un generico payload
variabile da qualche parte al di fuori del mio controllo (cioè non posso cambiare il tipo):Mixing Scala e Java: come ottenere un parametro costruttore generico correttamente?
// Java code
Wrapper<? extends SomeBaseType> payload = ...
ho ricevere ad un valore payload
come un parametro di metodo nel mio codice e voglio passarlo su Scala case class
(da utilizzare come messaggio con un sistema di attori), ma non ottenere le definizioni corrette in modo tale da non ottenere almeno un avviso del compilatore.
// still Java code
ScalaMessage msg = new ScalaMessage(payload);
Questo dà un avviso del compilatore "di sicurezza di tipo: contructor ... appartiene al tipo grezzo ..."
La Scala case class
è definito come:
// Scala code
case class ScalaMessage[T <: SomeBaseType](payload: Wrapper[T])
Come posso definire la classe del caso in modo tale che il codice venga compilato in modo pulito? (Purtroppo, cambiare il codice della classe Java Wrapper
o il tipo del parametro payload
non è un'opzione)
Aggiornato a chiarire l'origine del carico utile parametro
Aggiunto Per confronto, in Java posso definire un parametro proprio nello stesso modo come la variabile payload
è definita:
// Java code
void doSomethingWith(Wrapper<? extends SomeBaseType> payload) {}
e chiamarlo sulla struttura moderatamente
// Java code
doSomethingWith(payload)
Ma non posso istanziare per es. un oggetto Wrapper direttamente senza ricevere un avviso di tipo "raw". Qui, ho bisogno di usare un metodo static
aiutante:
static <T> Wrapper<T> of(T value) {
return new Wrapper<T>(value);
}
e usare questo helper statica a un'istanza di un oggetto Wrapper
:
// Java code
MyDerivedType value = ... // constructed elsewhere, actual type is not known!
Wrapper<? extends SomeBaseType> payload = Wrapper.of(value);
Soluzione
posso aggiungere un metodo di supporto simile a un oggetto compagno 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
}
e utilizzare questo da Java a un'istanza della classe ScalaMessage
w/o problemi:
// Java code
ScalaMessage msg = ScalaMessageHelper.apply(payload);
A meno che qualcuno esce con una soluzione più elegante, farò estrarre questo come una risposta ...
Grazie !
Non funzionerà perché in realtà ho un parametro metodo di tipo 'Wrapper estende SomeBaseType> 'in Java che viene passato nel blocco di codice di cui stiamo discutendo. Aggiornerò la domanda originale di conseguenza. –
Ho fatto un aggiornamento, controllalo. –