在activator template for simple rest API project in Scala中,Book.scala
文件如下所示。
package models
import play.api.libs.json.Json
object Book {
case class Book(name: String, author: String)
implicit val bookWrites = Json.writes[Book]
implicit val bookReads = Json.reads[Book]
var books = List(Book("TAOCP", "Knuth"), Book("SICP", "Sussman, Abelson"))
def addBook(b: Book) = books = books ::: List(b)
}
为什么里面有Book
个对象和Book
个案例类?为什么不只是一个Book
案例类(或只是一个Book
类而不是一个案例类)?上述结构有哪些优点/缺点?
答案 0 :(得分:2)
我确信这只是某个人放在一起的一个小例子,所以你不应该读太多。但它展示了一些人认为的反模式:在其他类中嵌套案例类。一些最佳实践指南,例如this one,建议避免在其他类中嵌套案例类,并且有充分的理由:
这很诱人,但你几乎不应该定义嵌套的case类 在另一个对象/类中,因为它与Java混淆 序列化。原因是当你序列化一个case类时 关闭“this”指针并序列化整个对象 如果你输入你的App对象意味着每个实例 案例类,你序列化整个世界。
具体案例类的内容是:
- 我希望案例类是不可变的(值,事实),因此
- 我希望案例类可以轻松序列化
醇>首选平面层次结构。
例如,这个小程序会出乎意料地抛出异常:
import java.io._
class Outer {
case class Inner(a: Int)
}
object Test extends App {
val inner = (new Outer).Inner(1)
val oos = new ObjectOutputStream(new FileOutputStream("/tmp/test"))
oos.writeObject(inner)
oos.close
}
如果此外部Book
对象的唯一目的是将常用功能组合在一起,则package
将是首选结构。
此外,即使由于某些其他原因需要object
,将该对象命名为与内部案例类相同也会造成混淆,特别是因为案例类会自动生成伴随对象。因此,在此示例中,有一个Book
对象,一个Book.Book
案例类,因此还有Book.Book
个伴随对象。
答案 1 :(得分:1)
Book对象在此代码中的作用更像是一个静态书籍utils / manager类,它包含一系列书籍。你可以想象这是一个库类,允许添加书籍。
Book case类只是Book实例的匿名类。正如m-z所说,这只是一个例子,对于更复杂的类,你可以把它移到一个独立的Book类。