Автоматически создавать геттеры для параметров класса (чтобы избежать классов классов)?

В Scala, если мы имеем

class Foo(bar:String)

Мы можем создать новый объект, но не можем получить доступ к bar

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

Однако, если мы объявим Foo как case class, это работает:

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

Из-за этого мне приходится делать многие из моих классов как классы классов. В противном случае, я должен написать шаблонный код для доступа к bar:

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

Итак, мои вопросы:

  • Есть ли способ "исправить" это без использования классов классов или шаблонов?
  • Использует ли классы case в этом контексте хорошую идею? (или каковы недостатки классов case?)

Я предполагаю, что второй заслуживает отдельного вопроса.

Ответ 1

Просто используйте ключевое слово val в конструкторе, чтобы сделать его общедоступным:

class Foo(val bar:String) {

}

Что касается вашего вопроса: если это единственная функция, которая вам нужна, не используйте классы case, просто пишите с помощью val.

Однако было бы здорово узнать, почему классы классов не очень хороши.

В случае, если классы все аргументы по умолчанию являются общедоступными, тогда как в простом классе все они закрыты. Но вы можете настроить это поведение:

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

scala> new Foo("public","private")
res0: Foo = [email protected]

scala> res0.bar
res1: String = public

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

И даже так:

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

Для классов case (благодаря @JamesIry):

case class Bar(`public`: String, private val `private`: String)  

Ответ 2

Вы можете использовать аннотацию BeanProperty для автоматического создания java-подобных геттеров

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

Теперь Foo имеет метод getBar, который возвращает значение bar.

Обратите внимание, что это полезно только в том случае, если у вас есть веская причина использовать java-подобные геттеры (типичные причины, по которым вам нужен ваш класс, чтобы быть надлежащим java bean, чтобы работать с java-библиотеками, которые ожидают java beans и использовать отражение для доступа к свойствам bean).

В противном случае просто войдите в значение bar напрямую, это "путь scala".

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