13

在 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
}

所以我的问题是:

  1. 有没有办法在不使用案例类或样板代码的情况下“解决”这个问题?
  2. 在这种情况下使用案例类是个好主意吗?(或者案例类的缺点是什么?)

我想第二个值得一个单独的问题。

4

2 回答 2

18

只需在构造函数中使用 val 关键字即可公开访问:

class Foo(val bar:String) {

}

至于您的问题:如果这是您需要的唯一功能,请不要使用案例类,只需使用val.

但是,很高兴知道为什么案例类不好。

在案例类中,所有参数默认都是公共的,而在普通类中它们都是私有的。但是您可以调整此行为:

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

甚至像这样:

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

对于案例类(感谢@JamesIry):

case class Bar(`public`: String, private val `private`: String)  
于 2012-09-10T15:32:48.740 回答
9

您可以使用 BeanProperty 注解自动生成类似 java 的 getter

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

现在 Foo 有一个返回bar值的 getBar 方法。

请注意,这仅在您有充分的理由使用类似 java 的 getter 时才有用(典型的原因是您需要您的类是正确的 java bean,以便与期望 java bean 并使用反射的 java 库一起工作访问 bean 的属性)。

否则,直接访问bar值,这就是“scala 方式”。

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

于 2012-09-10T15:31:58.483 回答