11

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?

David
  • 5,184
  • 3
  • 41
  • 67

2 Answers2

24

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
  • 20,435
  • 3
  • 55
  • 76
  • 1
    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 Oct 02 '10 at 22:01
  • Agreed, cool and +1, but only works if you have write access to the Object's source. Will not work for scala.xml.TopScope, for example. – Synesso Mar 08 '11 at 01:41
22
{ 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
  • 166,841
  • 26
  • 322
  • 407
  • 1
    Some explanation would be good. Is this a 'portable' method, or are the $'s an implementation artifact of Scala ? – Brian Agnew Oct 02 '10 at 13:02
  • @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 Oct 02 '10 at 13:33
  • Given `LocalEnvironment` seems to be a standalone singleton object, it should probably be `return LocalEnvironment.MODULE$` (no `$` in `LocalEnvironment`). – Fabian Steeg Oct 02 '10 at 13:59
  • 1
    @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 Oct 02 '10 at 15:46