0

我不确定我的主题是否正确。我将尝试描述问题。我有一个共同的领域特征。StringField 和 IntField 扩展了这个类:

trait BaseField[T] {
  def name = "field"

  var owner : FieldContainer

  var value : T
  def set(value : T) {
    this.value = value
    this.owner.fields.put(name, this)
  }
}


class StringField extends BaseField[String]
class IntField extends BaseField[Int]

如何实现 FieldContainer 类?我想要的是稍后匹配 FieldTypes:

val fieldContainer = {...init code here...}

fieldContainer.fields foreach {
  field -> {
     field match {
       case f: StringField => println("String")
       case f: IntField => println("Int")
       case _ => println("Unknown")
     }
  }
}

这是我的 FieldContainer(到目前为止)

trait FieldContainer {

  private metaFields : HashMap[String, Any] = new HashMap[String, Any]
  def fields : HashMap[String, Any] = this.metaFields
}

我以这种方式使用它:

class Pizza extends FieldContainer {

  object name extends StringField(this) {
    override def name = "pizza_name"
  }

  object pieces extends IntField(this) {
     override def name = "pieces_count"
  }
}
4

1 回答 1

1

字段不需要知道它们的所有者。

class BaseField[T](initValue: T, val name: String = "field") {
  private[this] var _value: T = initValue
  def apply() = _value
  def update(v: T) { _value = v }
  override def toString(): String = name + "(" + apply() + ")"
}

class StringField(initValue: String, name: String = "field") extends BaseField[String](initValue, name)
class IntField(initValue: Int, name: String = "field") extends BaseField[Int](initValue, name)

trait FieldContainer {
  protected def addField[C <: BaseField[_]](field: C): C = {
    _fields += (field.name -> field)
    field
  }

  protected def stringField(initValue: String, name: String): StringField =
    addField(new StringField(initValue, name))

  protected def intField(initValue: Int, name: String): IntField =
    addField(new IntField(initValue, name))

  private var _fields : Map[String, Any] = Map[String, Any]()
  def fields : Map[String, Any] = _fields
}

首次访问时初始化的对象(单例),因此您应该使用val而不是objectfor 字段:

class Pizza extends FieldContainer {

  val name = stringField("", "pizza_name")

  val pieces = intField(0, "pieces_count")

  val mass: BaseField[Double] = addField(new BaseField[Double](0, "mass"))
}

用法:

scala> val p = new Pizza()
p: Pizza = Pizza@8c61644

scala> p.fields
res0: Map[String,Any] = Map(pizza_name -> pizza_name(), pieces_count -> pieces_count(0), mass -> mass(0.0))

scala> p.name() = "new name"

scala> p.pieces() = 10

scala> p.mass() = 0.5

scala> p.fields
res4: Map[String,Any] = Map(pizza_name -> pizza_name(new name), pieces_count -> pieces_count(10), mass -> mass(0.5))

scala> p.name()
res5: String = new name

scala> p.pieces()
res6: Int = 10

scala> p.mass
res7: BaseField[Double] = mass(0.5)
于 2012-06-11T07:47:05.383 回答