4

販売注文を表すクラスがあります。

class SalesOrder(val f01:String, val f02:Int, ..., f50:Date)

fXXフィールドにはさまざまな種類があります。注文の監査証跡を作成するという問題に直面しています。クラスの 2 つのインスタンスが与えられた場合、どのフィールドが変更されたかを判断する必要があります。私は次のことを思いつきました:

class SalesOrder(val f01:String, val f02:Int, ..., val f50:Date){

  def auditDifferences(that:SalesOrder): List[String] = {

    def diff[A](fieldName:String, getField: SalesOrder => A) =
      if(getField(this) != getField(that)) Some(fieldName) else None

    val diffList = diff("f01", _.f01) :: diff("f02", _.f02) :: ...
                :: diff("f50", _.f50) :: Nil

    diffList.flatten
  }    
}

私は、コンパイラがすべての_.fXX関数で何をするのか疑問に思っていました: それらは一度だけ (静的に) インスタンス化され、クラスのすべてのインスタンスで共有できますか、それともクラスのインスタンスを作成するたびにインスタンス化されますか?

私の心配は、大量の SalesOrder インスタンスを使用するため、大量のガベージが作成される可能性があることです。別のアプローチを使用する必要がありますか?

4

2 に答える 2

2

この問題を解決する 1 つのクリーンな方法は、標準ライブラリのOrdering型クラスを使用することです。例えば:

class SalesOrder(val f01: String, val f02: Int, val f03: Char) {
  def diff(that: SalesOrder) = SalesOrder.fieldOrderings.collect {
    case (name, ord) if !ord.equiv(this, that) => name
  }
}

object SalesOrder {
  val fieldOrderings: List[(String, Ordering[SalesOrder])] = List(
    "f01" -> Ordering.by(_.f01),
    "f02" -> Ordering.by(_.f02),
    "f03" -> Ordering.by(_.f03)
  )
}

その後:

scala> val orderA = new SalesOrder("a", 1, 'a')
orderA: SalesOrder = SalesOrder@5827384f

scala> val orderB = new SalesOrder("b", 1, 'b')
orderB: SalesOrder = SalesOrder@3bf2e1c7

scala> orderA diff orderB
res0: List[String] = List(f01, f03)

元の定式化のパフォーマンスについて心配する必要はほとんどありませんが、このバージョンは (ほぼ間違いなく) 無関係な理由で優れています。

于 2013-06-30T23:35:19.733 に答える