Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala getters and setters in Java class

I would like to create a Java class that follows the Scala setters/getters convention.

I tried following simple class, but it does not work:

public class JavaA {
private int a = 0;

public int a() {
    return a;
}

public void a_$eq(int a) {
    this.a = a;
}
}

But when I try to access it from scala:

val x = new JavaA
x.a = 1

and I get "reassignment to val" error message. I tried to look for this, but all issues I found where the other way around from scala to java.

What is the right way to do it?

Thanks!

like image 453
fikovnik Avatar asked Jun 05 '12 12:06

fikovnik


People also ask

Which action will automatically create a getter and setter for a class in Scala?

When you define a class field as a var , Scala automatically generates getter and setter methods for the field, and defining a field as a val automatically generates a getter method, but you don't want either a getter or setter.

How do you define a class in Scala?

Defining a classThe keyword new is used to create an instance of the class. We call the class like a function, as User() , to create an instance of the class.

What is a getter accessor in Java?

Getters (a.k.a. Accessors) Getters, or accessors, are methods that provide access to an object's instance variables. In essence, we are providing a layer of indirection. Simple classes often have getters that return the associated instance variable and nothing more.


1 Answers

You can only sort of do this, and it's hard enough that you probably don't want to.

What you can't do is write a bare Java class that magically is interpreted as Scala getters and setters. The reason is that Scala embeds information into the class file that it requires for its getters and setters (e.g. are there zero parameter blocks or one empty parameter block--a distinction which is not preserved on the JVM (or in Java)).

What you can do is use Java to implement a Scala-defined interface (i.e. trait):

// GetSetA.scala
trait GetSetA { def a: Int; def a_=(a: Int): Unit }

// JavaUsesGSA.java
public class JavaUsesGSA implements GetSetA {
  private int a = 0;
  public int a() { return a; }
  public void a_$eq(int a) { this.a = a; }
}

What you can't do, even so, is use the class directly (again because Java does not add the appropriate annotation information for Scala):

scala> j.a = 5
<console>:8: error: reassignment to val
       j.a = 5

but since it does implement the trait successfully, you can use it as desired when it is typed as the trait:

scala> (j: GetSetA).a = 5
(j: GetSetA).a: Int = 5

So it's rather a mixed bag. Not perfect by any means, but it may be sufficiently functional to help out in some cases.

(The other alternative, of course, is to provide an implicit conversion from the Java class to one that has a getter/setter that references the real methods on the Java class; this works even when you can't have the Java inherit from Scala.)

(Edit: Of course there's no critical reason that the compiler must act this way; one could argue that interpreting Java-defined getter/setter pairs as if they were Scala ones (i.e. if the classfile does not explicitly say it's from Scala) is a good candidate for a feature enhancement to improve Java interoperability.)

like image 62
Rex Kerr Avatar answered Sep 17 '22 15:09

Rex Kerr