I want to call some Java code from Scala code. I would like to use Scala's apply construct, so I can call it like this:
val led = OutPin(0)
instead of:
val led = new OutPin(0)
I naively implemented an additional apply method in my Java code like this:
public class OutPin {
public OutPin(int pinNumber) {
}
public OutPin apply(int pinNumber) {
return new OutPin(pinNumber);
}
}
This does not make my Scala code (first line above) compile, and instead gives me an error:
Object OutPin is not a value
What is the correct way to implement Scala's apply method in Java?
Calling methods on Scala instances work exactly as in Java.ScalaClass scalaClass = new ScalaClass(true); assertEquals(2, scalaClass. plus(1, 1)); Note that Scala classes cannot have static methods. The convention is to put methods of static nature on companion objects.
Scala List apply() method with example. The apply() method is utilized to select an element in the list by its index. Return Type: It returns an element from the given list by its index which is present in the apply method as argument.
A Scala trait with no method implementation is just an interface at the bytecode level and can thus be used in Java code like any other interface.
The apply() method calls the specified function with a given this value, and arguments provided as an array (or an array-like object).
Your problem is not with the apply method per-se, but with trying to implement a Scala singleton object in Java.
I think (but am not certain) that this is very difficult, perhaps even impossible, by design.
Consider a very, very simple case:
object Obj;
This compiles to two JVM bytcode files, Obj$.class
and Obj.class
. 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:
Obj
, a Obj.class
and Obj$.class
must be generatedObj$
class must have a public final static
field of type Obj$
called MODULE$
, which will be initialized on class initialization refer to the singleton object. In Scala, calls to Obj.foo()
get mapped to Obj$.MODULE$.foo()
[...if Obj had a method called foo()
, that is!]Obj
class contains static functions that just forward to a call of a method of the same name and signature on Obj$.MODULE$
.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: javap -c -p -s -v <fully-qualified-class-name>
]
For example, the final static MODULE$
field is initialized indirectly by the static initializer. The static initializer just constructs an Obj$
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.
Also, the Obj
class (the version without the terminal dollar sign) includes an annotation of type ScalaSig, 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.
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.
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:
public class Cat {
public String apply( int i ) {
return "Meow: " + i;
}
}
Here's a use of Scala's sugared apply:
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> val Morris = new Cat;
Morris: Cat = Cat@6b4feafa
scala> Morris(8)
res0: String = Meow: 8
If you want an apply method that is usable in Scala you should implement it on the scala an side using object
to wrap your java class with the same name of the class which instantiate it
object OutPin {
def apply(pinNumber :Int) = new OutPin(pinNumber)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With