Give the simple class
class MyClass {
private var myVar: String = _
}
How can I generate the setters and getters for myVar?
The Code | Generate menu shows:
Override Methods...
Implement Methods...
Delegate Methods...
Copyright
equals() and hashCode()
toString()
Companion object
IntelliJ version: 14.1.5
OS: OS X 10.10.5
#Zoltán is right - getters and setters are not common in Scala because:
Scala encourages immutability
Scala already generates them for you when make a field - they just aren't named according to the Java beans convention (You can encourage Scala to not generate these methods by being really restrictive in who can see and modify the field - think final private[this] val).
Because of #2, it is possible to go from var someField to private var _someField, def someField = this._someField and def someField_=(value: String) = { this._someField = value } and not have consumers update their code. In other words, the change is source compatible (though I believe it is not binary compatible).
If you need Java bean style getters and setters simply annotate the field with #BeanProperty and scalac will generate the getter and setter for you:
import scala.beans.BeanProperty
class MyClass {
#BeanProperty
var myVar: String = _
}
Note that in order to get the is getters and setters for a boolean property you need to use BooleanBeanProperty instead.
You can use the Scala Bean Property
import scala.beans.BeanProperty
class MyClass {
#BeanProperty var myVar: String = _
}
#BeanProperty - Generates getters and setters for a property. (Or
just a getter if the bean is a val)
Related
I have a simple Spring boot app with a Scala class...
case class TestThing(val name: String ){
#Getter
#Setter
var value = null
def getMap = {
val list: List[Item] = List(Item("1", "Foo"), Item("2", "Bar"))
val map = list.map(item => item.key -> item).toMap
map("1")
}
}
Now I am trying to access the getter and setter function from a java class like this...
#GetMapping("/other")
public String index(){
TestThing thing = new TestThing("My Name");
thing.setValue("Test");
return "Hello World from me "+thing.getMap().value()+"||"+thing.getValue();
}
The thing.getMap() works fine but I get the following compile error for the getters and setters...
error: cannot find symbol
return "Hello World from me "+thing.getMap().value()+"||"+thing.getValue();
^
symbol: method getValue()
location: variable thing of type TestThing
What am I missing? I found this question (Error compiling Java/Scala mixed project and Lombok) but it is the reverse and doesn't seem to help.
Lombok doesn't work with Scala. Simple as that. (It is even described why in the issue you linked). The #Getter and #Setter annotations in Scala classes are never processed and the accessors are never generated.
It is also completely unneeded as case classes generate: toString, equals, hashcode getters and setter. If you want to have Java Bean accessors you can use #BeanProperty annotation.
import scala.beans.BeanProperty
case class TestThing(val name: String ){
#BeanProperty
var value: String = null
}
val test = TestThing("test")
test.getValue // null
test.setValue("test")
test.getValue // "test"
When inheriting from a Java class with public members, using scala's override modifier raises compilation error like so:
Error:(67, 22) overriding variable userId in class Logon of type String;
value userId has incompatible type
override val userId = s.user
^
The java class looks something along the following lines:
public class Logon {
public String userId = "";
}
and the scala code:
class MyLogon extends Logon {
override val userId : String = "abc"
}
Removing the modifier results in:
Error:(72, 7) overriding variable userId in class Logon of type String;
value userId needs `override' modifier
val userId: String = s.user
^
Why is this? Is it a bug? There are related questions e.g. 16607517 but these seem to be changing the visibility of the fields; that's not the case here - they're all public.
Believe this is with scalac-2.10.4.
It is impossible to override public fields defined in Java because of how it is implemented in Scala:
A public field (val user: String) is represented internally as a combination of private field (say, private val user$1: String) and public accessor method (def user: String = user$1). It is not allowed to override a field with a method, thus the compile error.
There is currently no way to omit the public accessor method generation in Scala, so you'll have to find other ways to implement what you want - either by defining a common trait or interface, or by using another field name, or by wrapping the Java Logon into a Scala Logon with proper superclass constructs.
Scala interoperates extremely well with Java, but the interop is not perfect, unfortunately.
You cannot override member variables.
This should not be confused with how scala allows to override val & var which works because scala compiler generates getter and setter methods for them.
Defining data members in a class that can be publicly accessed/modified
var _foo: Int = _
def foo_(foo: Int) = _foo = foo // setter function
def foo = _foo // getter function
Is it a good practice to convert this using annotation #BeanProperty?
import scala.reflect.BeanProperty
#BeanProperty var foo: Int = _
and when to use this annotation and when not to?
There's some redundancy in your first example, since defining a var already results in the generation of getters and setters. For example, if we compile this class:
class Foo {
var foo: Int = _
}
Then javap -private Foo shows the following:
public class Foo {
private int foo;
public int foo();
public void foo_$eq(int);
public Foo();
}
Unless you have custom logic that you need to fit into your getters or setters (in which case it's often a good idea to consider more descriptive method names, anyway), you shouldn't need to define them manually.
The scala.reflect.BeanProperty annotation (or scala.beans.BeanProperty on 2.11) doesn't have any effect on the generation of the foo() and foo_$eq(int) methods—the compiler will generate these for a var foo: Int whether or not you use the annotation. The annotation simply adds getFoo and setFoo aliases for these methods. If you need these aliases, use the annotation, and if you don't, don't.
To summarize best practices:
Don't use var.
If you have to use var, you can (and should) avoid defining your own getters and setters.
Use the BeanProperty annotation only if you're implementing an interface with getFoo and setFoo-style method signatures, or if you're expecting your code to be called from Java (where calling methods with names like foo_$eq is inconvenient).
#BeanProperty is meant for Java interoperability, in particular with reflection-based Java frameworks expecting get and set methods.
Do not use it if you're staying in the Scala world. Use Scala getters (def foo) and setters (def foo_=) instead.
I want to define a trait that is used by Java code and it would be therefore convenient to have Java-friendly setters and getters for its members. The #BeanProperty annotation does that for me, but I can't get it to work with members that are left undefined in the trait. The following:
import scala.beans.BeanProperty
trait A {
#BeanProperty var useFoo: Boolean
}
yields the warning no valid targets for annotation on method useFoo - it is discarded unused. You may specify targets with meta-annotations, e.g. #(scala.beans.BeanProperty #getter) trait A { #BeanProperty var useFoo: Boolean }
However, it is not discarded unused. A class extending the above trait, for example
class B extends A {
var useFoo = false
}
is correctly rejected by the compiler as it does not implement the getter and setter of the BeanProperty. Annotating the useFoo field in class B with #BeanProperty makes it work as expected. However, this seems not to be the proper way to do this, since the above warning is generated. The documentation for meta annotations suggests that targets are only useful if you want to propagate other annotations onto the generated accessors. So, what is the proper way to define the above trait?
It happens to be a bug in Scala 2.11.x: https://issues.scala-lang.org/browse/SI-8813
My search didn't turn up this issue as in 2.11.1 the warning is "no valid targets for annotation on method", while in 2.11.2 it's "no valid targets for annotation on value"
In Scala, I have a case class:
case class MonthSelectionInfo(monthSelection: MonthSelection.Value, customMonth:Int = 0, customYear:Int = 0) {
def this(monthSelection: MonthSelection.Value) = {
this(monthSelection, 0, 0)
}
}
object MonthSelection extends Enumeration {
type MonthSelection = Value
val LastMonth, ThisMonth, NextMonth, CustomMonth = Value
}
When I have an instance of the case class, I have to use
myMonthSelectionInfo.monthSelection
and
myMonthSelectionInfo.eq(newMonthSelection)
to get & set the MonthSelection instance contained within.
Is there any nice Scala way to format the getter & setter to look more like regular Java POJOs? e.g.
myMonthSelectionInfo.setMonthSelection(newMonthSelection)
There is #BeanProperty annotation to generate getters and setters for fields.
case class MonthSelectionInfo(#reflect.BeanProperty var monthSelection: MonthSelection.Value)
scala> val ms = MonthSelectionInfo(MonthSelection.LastMonth)
ms: MonthSelectionInfo = MonthSelectionInfo(LastMonth)
scala> ms.setMonthSelection(MonthSelection.ThisMonth)
sscala> ms.getMonthSelection
res4: MonthSelection.Value = ThisMonth
In object oriented programming, getters and setters are something that most would agree have some real world benefits. Unfortunately, they can sometimes be annoying to write. They usually do not consist of a lot of code , but when you have the write the same thing over and over and over it gets old really fast. In my experience, most getters and setters are very much alike so it stands to reason that there must be a “better” way to accomplish the same result.
This link may help you.
We can use #BeanProperty in scala 2.11
import scala.beans.BeanProperty
case class Employee(#BeanProperty id: Long, #BeanProperty name: String, #BeanProperty age: Long)