我不确定我的主题是否合适。我会试着描述一下这个问题。 我有一个共同的领域特征。 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"
}
}
答案 0 :(得分: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
代替object
字段:
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)