How can I provide a scala companion object's class to Java? - scala

I have a Java code that looks for annotations in static methods of a class.
processor.readStatics( MyClass.class ); // Takes Class<?>
How can I provide the methods of a scala companion object to this function from within scala?
class MyClass {
}
object MyClass {
def hello() { println("Hello (object)") }
}
I seems that:
MyClass$.MODULE$.getClass()
should be the answer. However, MyClass$ seems to be missing from scala (in 2.10, at least) and only visible to Java.
println( Class.forName("MyClass$.MODULE$") )
also fails.

Class name is MyClass$ (with the appropriate package name prepended).
println(Class.forName("MyClass$")) will print out "class MyClass$".
MyClass$.MODULE$ is the instance of the class, referencing the singleton object.
println(MyClass$.MODULE$ == MyClass) will print out "true" even though, when compiling, you will get a warning that this comparison always yields false :)
Note, that none of this works in repl for some reason. You need to actually create a .scala file, compile it with scalac, and run.
So, in java, use MyClass$ to reference the class of MyClass object statically, use MyClass$.MODULE$ to reference the singleton instance of MyClass object, use MyClass$.class or MyClass$.MODULE$.getClass() to reference the class of the singleton object dynamically, use Class.forName("MyClass$") to access it at runtime by name.

The shortest and type-safest solution is to simply use
MyClass.getClass
I would have hoped the following to work, but apparently scalac is not happy with it:
classOf[MyClass.type]

Related

How do you create a ScalaMock stub that doesn't call the constructor of the underlying object?

Consider the following example Scala class and unit test:
class BrokenClass(s: String) {
private val len = s.length
def length(): Int = len
}
class BrokenTest extends FlatSpec with Matchers with MockFactory {
"A BrokenClass" should "stub correctly" in {
val stubThing = stub[BrokenClass]
(stubThing.length _) when () returns (10)
stubThing.length should equal (10)
}
}
In older versions of ScalaMock, this code would work. With Scala 2.12 and ScalaMock 3.6, I'm getting a NullPointerException because even though I'm creating a stub, it's still invoking the "s.length" line of the constructor of BrokenClass. So it's trying to dereference "s", which is null because I haven't passed anything to it because all I want is a stub that returns a specific value when a specific method is called.
Is there a way to create a stub without it trying to invoke the object's constructor? Why did this work in older versions?
ScalaMock generates subclasses using a macro definition.
That macro gets expanded/evaluated during the compiler run.
As mocks are subclasses, the constructors of the superclasses will be called - no exceptions.
You might be able to work around this using some cglib sorcery, but that is not something i am familiar with.
So this may have been possible in older ScalaMock versions but this feature is not coming back anytime soon with the current implementation.
another option is to actually subclass this thing yourself and mock the subclass
class NotSoBrokenClass extends BrokenClass("")
...
val nsb = mock[NotSoBrokenClass]
...
That works in some cases, but if the constructor depends on non-final method calls you'll see funny behaviour (e.g. NPEs) too.

Explain this behaviour of scala class

I was wondering about this behaviour of scala class which is shown in the code snippet. The execution of following code prints hi , my confusion is what goes on in the background that without any method and field definition the invocation of TestClass executes the bare code? Also why is such kind of bare code writing within a class is allowed ?
class TestClass {
if(true)
println("hi")
}
object TestObject extends App{
val ci = new TestClass
}
The body of a class, object or trait (except for method definitions) is its (primary) constructor. It's more complicated for classes and object extending DelayedInit (or App, which extends DelayedInit).
The special syntax of 'bare' code inside classes is Scala's equivalent of Java's initializers / anonymous constructors that use braces around the code. Both initializers in Java and the code in your Scala class are executed on object creation, which is what you do inside your TestObject when calling the TestClass constructor with new.

Avoid duplicate type alias in Scala class and companion object

I'm a newbie in Scala, and I have a Scala program with a class and a companion object, and I want to use a type alias that is used :
To define the methods of the class.
Also I want to use the alias outside the class. For that I find useful to define the alias in the companion object, to import the alias from the companion object. I also have some implicits defined in the companion object so this is just natural.
The concrete code is available at https://github.com/juanrh/Surus/blob/1cfd55ed49c4d1b22e53babe07bcf44fd74e3072/src/main/scala/org/surus/spark/SurusRDDFunctions.scala, the type alias is PMMLPrediction and the class is SurusRDDFunctions. Currently the code works but I have defined the alias both in the class and the companion, which is not very nice. If I remove the definition of the alias in the class then the class is not able to find it, which seems weird. So I think I'm probably doing something wrong, any ideas?
Thanks a lot in advance for your help!
Greetings,
Juan
Given the companion object
object Example {
type MyString = String
}
You can access the type directly through to the companion object
class Example (val name: Example.MyString) { }
Or by importing it from the companion object
class Example {
import Example._
val name: MyString = "example"
}

I can haz no package-private class in Scala?

Sorry for the catchy title. ;-)
I want to create a package-private class with a package-private method in Scala, so my class looks somewhat like this:
package net.java.truevfs.ext.pace
import ...
private[pace] abstract class AspectController(controller: FsController)
extends FsDecoratingController(controller) {
private[pace] def apply[V](operation: => V): V
... // lots of other stuff
}
However, if I use javap to check what the Scala compiler effectively creates, I get something like this:
$ javap -classpath target/classes net.java.truevfs.ext.pace.AspectController
Compiled from "AspectController.scala"
public abstract class net.java.truevfs.ext.pace.AspectController extends net.java.truevfs.kernel.spec.FsDecoratingController implements scala.ScalaObject{
public abstract java.lang.Object apply(scala.Function0);
...
}
This means that although the Scala compiler might respect the access restrictions, I could still call this class from any Java code, which is a clear encapsulation violation.
Am I missing something?
Is there a way to make this work as intended?
In addition to #RĂ©gis' answer, the reason Scala compiler doesn't make the class package-private is because by Scala rules it can be accessed from other packages: namely, subpackages of net.java.truevfs.ext.pace. E.g.
package net.java.truevfs.ext.pace.subpackage
import net.java.truevfs.ext.pace.AspectController
class Subclass extends AspectController { ... }
is legal in Scala, but in Java classes from net.java.truevfs.ext.pace.subpackage can't access package-private classes from net.java.truevfs.ext.pace.
You are not missing anything.
Many of the access restricitons in scala have no equivalent in java nor at the jvm level. The additional information is obviously right there in the .class file, but is there as custom annotations that only the scala compiler will interpret.
The scala object model can only partly be matched to the jvm object model, and a java compiler will only see this partial model.
I'd say that the match is pretty close and the scala compiler does a very good job at java interoperability, but nothings's perfect.
Not really a 100% correct answer...
You can make a package object if I want to do some fancy stuff in there with a private class. The package object is accessed like any other package.
The class MyClass is package private to that package object.
It's not package private however.
package object com.jasongoodwin.foo {
private class MyClass
class AnotherClass {
val myClass = new MyClass
}
}

scala: annotating accessor methods

class Foo {
#SomeAnnotation
var bar: String = _
}
#SomeAnnotation is a Java annotation (so it is kept at runtime) with runtime retention and Method target. The code compiles, but at runtime the bar() and bar_=() methods that the compiler generated are not annotated.
Assuming this is not a bug, is there a clean way of annotating the generated getter method without needing to def the method explicitly?
This mailing list post might be of use:
http://old.nabble.com/-scala--field-annotations,-getters-setters-and-BeanProperty-td24970781.html
Yes, you need to use the meta-annotations in scala.annotation.target. See the documentation in https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala/annotation/target/getter.scala