Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Your problem is not with the apply method per-se, but with trying to implement a Scala singleton object in Java.</p> <p>I think (but am not certain) that this is very difficult, perhaps even impossible, by design.</p> <p>Consider a very, very simple case:</p> <pre><code>object Obj; </code></pre> <p>This compiles to two JVM bytcode files, <code>Obj$.class</code> and <code>Obj.class</code>. In theory, it should be easy to just inspect the bytecode of those two classes, and reexpress the same thing in Java. The basic structure of Scala singleton objects is very, very simple:</p> <ol> <li>For a singleton object <code>Obj</code>, a <code>Obj.class</code> and <code>Obj$.class</code> must be generated</li> <li>The <code>Obj$</code> class must have a <code>public final static</code> field of type <code>Obj$</code> called <code>MODULE$</code>, which will be initialized on class initialization refer to the singleton object. In Scala, calls to <code>Obj.foo()</code> get mapped to <code>Obj$.MODULE$.foo()</code> [...if Obj had a method called <code>foo()</code>, that is!]</li> <li>The Java compiler doesn't know anything about these Scala generated class pairs, so for Java interop, the <code>Obj</code> class contains static functions that just forward to a call of a method of the same name and signature on <code>Obj$.MODULE$</code>.</li> </ol> <p>That sounds complicated, but it's really not so much. It's trivial to write a pair of Java classes that goes this far. But the Scala compiler (2.10.3) still won't recognize the pair as constituting a Scala singleton. Diving into the bytecode of a Scala-compiler generated singleton, you'll see that there are details that are hard to express in legal Java. [Hint: <code>javap -c -p -s -v &lt;fully-qualified-class-name&gt;</code>]</p> <p>For example, the final static <code>MODULE$</code> field is initialized indirectly by the static initializer. The static initializer just constructs an <code>Obj$</code> object, without directly assigning it. The assignment occurs within the private constructor. That's illegal in Java: blank static finals must be certainly initialized in the static initializer, and cannot be assigned in code (like the private constructor) that might potentially be called from outside the initializer and multiple times. The Scala compiler generates bytecode that respects the blank final semantics (because the private constructor is only called once), but exceeds the Java compiler's ability to verify those semantics. So this code would be rejected if expressed in Java.</p> <p>Also, the <code>Obj</code> class (the version without the terminal dollar sign) includes an annotation of type <a href="http://www.scala-lang.org/files/archive/nightly/docs-2.10.2/scalap/index.html#scala.tools.scalap.scalax.rules.scalasig.ScalaSig" rel="nofollow">ScalaSig</a>, which looks quite complicated and would be hard to reproduce by hand (in Java or in Scala), at least for those of us unsure exactly how this annotation works.</p> <p>I don't know exactly what the Scala compiler looks for before deciding to treat a pair of classes as a "value", that is a valid Scala singleton object, but Scala's designers have chosen not to make it easy, despite the simplicity of the basic scheme. Probably they wish to preserve the ability to reorganize how scala singleton objects translate to bytecode. Letting Java programmers synthesize scala singleton objects would effectively render the current scheme a permanent part of Scala's public API.</p> <p>Note that writing an ordinary, non-singleton class whose instances have an apply(...) method and so can be called like functions is easy from Java and works fine. Here's a Java cat:</p> <pre><code>public class Cat { public String apply( int i ) { return "Meow: " + i; } } </code></pre> <p>Here's a use of Scala's sugared apply:</p> <pre><code>Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_45). Type in expressions to have them evaluated. Type :help for more information. scala&gt; val Morris = new Cat; Morris: Cat = Cat@6b4feafa scala&gt; Morris(8) res0: String = Meow: 8 </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload