views:

134

answers:

2

I want to return from a Java method a reference to a Scala object. How can I do that?

My Scala objects are like this:

trait Environment 

object LocalEnvironment extends Environment {...}
object ServerEnvironment extends Environment {...}

... and I want my Java method to be like this:

Environment getEnvironment() { return LocalEnvironment; }  // DOES NOT COMPILE

Is there a way to do this?

+8  A: 
{ return LocalEnvironment$.MODULE$; }

should work.


Edit: the reason why this works is that this is how Scala represents singleton objects. The class ObjectName$ has a field in it called MODULE$ that is populated with the single valid instance of that class. But there is also a class called ObjectName that copies all the methods as static methods. That way you can use it like Java (just call ObjectName.methodName) in most cases, and Scala gets to have a real class to pass around.

But when Java needs to pass the class around--not something normally done with a bunch of static methods, which is what object is designed to emulate in Java--you then have to know how Scala represents it internally.

Rex Kerr
Some explanation would be good. Is this a 'portable' method, or are the $'s an implementation artifact of Scala ?
Brian Agnew
@Brian - I've partially answered in the edit. I'm not sure what you mean by 'portable' in contrast to 'implementation artifact'. It's both--Scala uses a consistent naming scheme for its implementation artifacts. Unlike anonymous closures, this one is easy to predict.
Rex Kerr
Given `LocalEnvironment` seems to be a standalone singleton object, it should probably be `return LocalEnvironment.MODULE$` (no `$` in `LocalEnvironment`).
Fabian Steeg
@Fabian - That doesn't work. The `LocalEnvironment` class will contain exactly and only those static methods needed to copy the (non-static) methods in the Scala singleton. `MODULE$` is not one of those methods--it is a field of the `LocalEnvironment$` class that is instantiated in a single copy (i.e. `LocalEnvironment$` is the class that contains implementation details, and `MODULE$` is an implementation detail within it).
Rex Kerr
@Rex: Ah, thanks!
Fabian Steeg
+6  A: 

While the $.MODULE$ method works, a slightly less jarring way to get Java-interop with Scala objects is to expose the object as a method on itself.

The Scala:

object LocalEnvironment extends Environment{
   def instance = this
}

The Java:

Environment getEnvironment() { return LocalEnvironment.instance(); }  

This works because under the covers, .instance() is implemented as a static method on class LocalEnvironment. There has been some discussion about Scala objects getting an "instance" method by default, for just this purpose.

Dave Griffith
This is cool, but it would need some comments to explain the purpose of the variable. For that reason, I've gone with the MODULE$ thing instead.
David