Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically make getters for class parameters (to avoid case classes)?

Tags:

scala

In Scala, if we have

class Foo(bar:String)

We can create a new object but cannot access bar

val foo = new Foo("Hello")
foo.bar // gives error

However, if we declare Foo to be a case class this works:

case class Foo(bar:String) 
val foo = Foo("hello")
foo.bar // works

I am forced to make many of my classes as case classes because of this. Otherwise, I have to write boilerplate code for accessing bar:

class Foo(bar:String) {
  val getbar = bar
}

So my questions are:

  1. Is there any way to "fix" this without using case classes or boilerplate code?
  2. Is using case classes in this context a good idea? (or what are the disadvantages of case classes?)

I guess the second one deserves a separate question.

like image 363
Jus12 Avatar asked Sep 10 '12 15:09

Jus12


2 Answers

Just use val keyword in constructor to make it publicly accessible:

class Foo(val bar:String) {

}

As for your question: if this is the only feature you need, don't use case classes, just write with val.

However, would be great to know why case classes are not good.

In case classes all arguments by default are public, whereas in plain class they're all private. But you may tune this behaviour:

scala> class Foo(val bar:String, baz: String)
defined class Foo

scala> new Foo("public","private")
res0: Foo = Foo@31d5e2

scala> res0.bar
res1: String = public

scala> res0.baz
<console>:10: error: value baz is not a member of Foo
              res0.baz

And even like that:

class Foo(private[mypackage] val bar:String) {
  // will be visible only to things in `mypackage`
}

For case classes (thanks to @JamesIry):

case class Bar(`public`: String, private val `private`: String)  
like image 69
om-nom-nom Avatar answered Sep 28 '22 09:09

om-nom-nom


You can use the BeanProperty annotation to automatically generate java-like getters

import scala.reflect.BeanProperty
case class Foo(@BeanProperty bar:String) 

Now Foo has a getBar method that returns the bar value.

Note though that this is only useful if you have a good reason to use java-like getters (typical reasons being that you need your class to be a proper java bean, so as to work with java libraries that expect java beans and use reflection to access the bean's properties).

Otherwise, just access the bar value directly, this is "the scala way".

See http://www.scala-lang.org/api/current/index.html#scala.reflect.BeanProperty

like image 26
Régis Jean-Gilles Avatar answered Sep 28 '22 08:09

Régis Jean-Gilles