现在我有类似的课程:
abstract class Record {
// Required fields
val productCode:Option[String]
val price:Option[Double]
// Optional fields
val notes:Option[String] = None
val used:Option[Boolean] = Option(false)
}
然后创建它们:
val r = new Record {
override val productCode = Option("abc")
override val price = Option(32.12)
}
有几点需要注意:
如果子类混合了新的字段,这使得质量分配(我正在做,因为我有一个字段数组)很难,例如:
override val List(productCode, price, discount) = fields // fields is a List
将无法编译,因为超类中未定义discount
,因此没有覆盖。我不确定是否有办法做到这一点。
我的主要问题是:
e.g。 (伪代码}:
val r2 = r.clone { override val used = true }
我听说2.8为案例类引入了类似的东西,但是在一种鼓励不可变数据结构的语言中,我会惊讶地发现在2.8之前这并不容易。我还在2.7。
答案 0 :(得分:2)
克隆实例没有简单的方法。 FWIW,不可变数据结构通常很深。例如,List
类只有两个成员:hd
和tl
。通过链接成员来增加列表。
您通过创建最少量的新数据结构并尽可能多地重新引用旧数据结构来克隆此类结构。通常,这是通过完成的 递归。
您可以在Purely Functional Data Structures一书中了解更多相关信息。该书所依据的paper免费提供。
您可以在此处查找Scala问题,以查看处理Option数据的有趣方法。不幸的是,我对你的其他问题没有任何解决方案。
答案 1 :(得分:2)
这看起来是2.8中非常重要的问题:
case class Employee(name: String, age: Int)
val joe = Employee("Joe", 25)
val bob = joe copy (name = "Bob")
将此与默认值相结合,您给出的示例可以轻松地重写为案例类,我认为这是实现不可变数据类型的“正确”方法。 (我不确定scala是否属实,但是来自ocaml / haskell,似乎是正确的。)
在2.7中你将不得不实现许多辅助函数:
def asUsed(r: Record): Record = {
Record(r.productCode, r.price, r.nodes, Some(true))
}
呸。他们应该真的快点2.8 ......
答案 2 :(得分:0)
使用Option
一个不可选的字段对我来说似乎很疯狂:为什么?
答案 3 :(得分:0)
正如已经说过的那样,在当前(2.7)Scala中没有直接的方法可以做到这一点,但从我的角度来看,使用构建器模式可以很容易地完成它。代码演示:
abstract class Record {
// Required fields
val productCode:Option[String]
val price:Option[Double]
// Optional fields
val notes:Option[String] = None
val used:Option[Boolean] = Option(false)
}
class RecordBuilder{
private var _productCode:Option[String] = null
private var _price:Option[Double] = null
// Optional fields
private var _notes:Option[String] = None
private var _used:Option[Boolean] = Option(false)
def productCode(in:Option[String]) : RecordBuilder = {
_productCode = in
this
}
def price(in : Option[Double]) : RecordBuilder = {
_price = in
this
}
def notes(in:Option[String]) : RecordBuilder = {
_notes = in
this
}
def used (in : Option[Boolean]) : RecordBuilder = {
_used = in
this
}
def create() : Record = {
val r = new Record = {
override productCode = _productCode
override price = _price
override notes = _notes
override used = _used
}
r
}
}
object Record{
def from(in:Record) : RecordBuilder = {
val r = new RecordBuilder
r.productCode(in.productCode).price(in.price).notes(in.notes)
.used(in.used)
}
}
object Test {
def main(args:Array[String]) = {
val r = new Record {
override val productCode = Option("abc")
override val price = Option(32.12)}
}
val r1 = Record.from(r).used(true).create
}
答案 4 :(得分:0)
镜头是操作不可变数据结构的绝佳工具。请参阅this question。