2010-10-05 24 views
8

J'évalue actuellement Scala pour de futurs projets et je suis tombé sur quelque chose d'étrange. J'ai créé la constante suivante pour nous dans une JSP:Utiliser les constantes Scala en Java

Et cela n'a pas fonctionné. Après quelques expériences j'ai décidé de décompiler pour aller au fond:

private final java.lang.String FORMATED_TIME; 

public java.lang.String FORMATED_TIME(); 
    Code: 
    0: aload_0 
    1: getfield #25; //Field FORMATED_TIME:Ljava/lang/String; 
    4: areturn 

Maintenant c'est intéressant! Personnellement, je me demandais depuis un certain temps pourquoi un inspecteur a besoin du préfixe obtenir et un mutateur le préfixe définir en Java car ils vivent dans des espaces de noms différents.

Cependant, il pourrait être difficile d'expliquer cela au reste de l'équipe. Alors est-il possible d'avoir une constante publique sans l'inspecteur?

Répondre

11

Ceci est dû à la Uniform Access Principle, à savoir: méthodes et les champs sont distinguables

Voir this answer

Dans Scala 2.8.0 cela signifie que si vous avez un objet compagnon, vous perdez votre statique transitaires)

Si vous avez ce à Scala:

//Scala 
object CommonControler { 
     val FORMATED_TIME = "formatedTime"; 
} 

Vous pouvez l'utiliser comme celui-ci de Java

//Java 

// Variables become methods 
CommonControler$.MODULE$.FORMATED_TIME(); 
// A static forwarder is avaliable 
CommonControler.FORMATED_TIME(); 

Voir aussi le livre Scala in Depth

A noter également la @scala.reflect.BeanProperty pour les classes.

+0

Je dois vérifier à nouveau - parce que je Je manque le transitaire.J'ai eu un porteur dans la 2ème classe que j'ai créée. – Martin

+1

Je pense que je l'ai compris. Si vous avez une classe CommonControler et un objet CommonControler, vous n'avez pas les redirecteurs statiques :-(. – Martin

1

J'ai examiné de plus près le code décompilé et noté quelque chose d'autre. Les variables ne sont pas réellement statiques. Donc, ma prochaine idée était d'utiliser un objet à la place:

object KommenControler 
{ 
    val FORMATED_TIME = "formatedTime"; 
} // KommenControler 

Mais maintenant, les choses tournent vraiment moche:

public final class ….KommenControler$ extends java.lang.Object implements scala.ScalaObject{ 

public static final ….KommenControler$ MODULE$; 

private final java.lang.String FORMATED_TIME; 

public static {}; 
    Code: 
    0: new #9; //class …/KommenControler$ 
    3: invokespecial #12; //Method "<init>":()V 
    6: return 

public java.lang.String FORMATED_TIME(); 
    Code: 
    0: aload_0 
    1: getfield #26; //Field FORMATED_TIME:Ljava/lang/String; 
    4: areturn 

Alors je reçois une classe supplémentaire se terminant le $ qui a une instance singleton appelée Moudle $. Et il y a toujours l'inspecteur. Ainsi, l'accès à la variable dans une jsp devient:

final String formatedTime = (String) request.getAttribute (….KommenControler$.MODULE$.FORMATED_TIME()); 

Cela fonctionne comme prévu et je peux personnellement vivre avec elle, mais comment vais-je expliquer à l'équipe?

Bien sûr, s'il y a un moyen plus simple, j'aime en entendre parler.

+1

Vous devriez l'inclure dans un joli objet java pour résumer l'appel laid mais nécessaire. En fait, en Java, vous devriez toujours encapsuler les constantes finales statiques publiques dans l'appel de méthode pour éviter qu'elles soient inliées lors de la compilation. – paradigmatic

+0

Voir cette réponse: http://stackoverflow.com/questions/3282653/how-do-you-call-a-scala-singleton-method-from-java/3445597#3445597 – oluies