我有一个这样的课程,如果有人感兴趣,我会详细解答重叠算法的哪一部分出错了,我希望将来在数据中增加许多其他可能的无效性。
case class Validity(grouping: Boolean = true,
matchingValuesValidation: Boolean = true) {
def compute: Boolean =
List(grouping,
matchingValuesValidation
).forall(identity)
def merge(ot: Validity): Validity =
Validity(
grouping && ot.grouping,
matchingValuesValidation && ot.matchingValuesValidation
)
}
我知道所有字段都是布尔值,计算不会改变。我想让方法计算和合并以某种方式遍历所有字段,所以如果我增强它,就不需要做3次。如果我使用Map,我可以添加我想要的任何键 - >值对,这是不可取的,我想保留结构。同时,我想通过简单地向该类添加另一个布尔参数来增强该类。非常感谢任何想法,提前感谢
你知道吗? YOLO。
case class Validity(grouping: Boolean = true, matchingValuesValidation: Boolean = true) {
def values: List[Boolean] = {
import scala.reflect.runtime.universe._
val fields = typeOf[Validity].members.collect { case m: MethodSymbol if m.isCaseAccessor => m }.toList
val mirror = runtimeMirror(this.getClass.getClassLoader)
fields.map(mirror.reflect(this).reflectField(_).get.asInstanceOf[Boolean])
}
def compute: Boolean = values.forall(identity)
def merge(ot: Validity) = Validity.fromValues(this.values.zip(ot.values).map(v => v._1 && v._2).reverse)
}
object Validity {
def fromValues(values: List[Boolean]): Validity = {
import scala.reflect.runtime.universe._
val mirror = runtimeMirror(Validity.getClass.getClassLoader)
val constructorSymbol = typeOf[Validity].decl(termNames.CONSTRUCTOR).asMethod
val classSymbol = mirror.reflectClass(typeOf[Validity].typeSymbol.asClass)
val constructor = classSymbol.reflectConstructor(constructorSymbol)
constructor(values:_*).asInstanceOf[Validity]
}
}
而不是反射你可以使用无形来为你做繁重的工作:
import shapeless.ops.hlist.{Mapper, Zip}
import shapeless.{::, Generic, HList, HNil, Poly1}
private sealed trait lowPrioMergerMapper extends Poly1 {
implicit def mapperT[T]: Case.Aux[(T, T), T] = at[(T, T)] { case (v1, _) => v1}
}
private object MergerMapper extends lowPrioMergerMapper {
implicit def mapperBoolean: Case.Aux[(Boolean, Boolean), Boolean] = at[(Boolean, Boolean)] { case (v1, v2) => v1 && v2 }
}
def booleanFieldMerger[T, HL <: HList, ZOut <: HList](a: T, b: T)(
implicit
gen: Generic.Aux[T, HL],
zipWith: Zip.Aux[HL :: HL :: HNil, ZOut],
mapper: Mapper.Aux[MergerMapper.type ,ZOut, HL]
): T = {
val aRepr = gen.to(a)
val bRepr = gen.to(b)
gen.from((aRepr zip bRepr) map MergerMapper)
}
用法如下:
val validity = Validity()
val validity2 = Validity(a = false)
val validity3 = Validity(b = false)
val validity4 = Validity(a = false, b = false)
booleanFieldMerger(validity,validity2) shouldBe validity2
booleanFieldMerger(validity2,validity3) shouldBe validity4
List(validity2,validity3).fold(validity)((a,b) => booleanFieldMerger(a,b)) shouldBe validity4
并且为了评估您可以使用的字段:
import shapeless.HList
import shapeless.ops.hlist._
def evaluateBooleanFields[T, HL <: HList](input: T)(
implicit
gen: Generic.Aux[T, HL],
toTrav: ToList[HL,Any]): Boolean = {
gen.to(input).toList.foldLeft(true){
case (acc, e: Boolean) => acc && e
case (acc, _) => acc}
}
用法与上面相同:
evaluateBooleanFields(validity) shouldBe true
evaluateBooleanFields(validity2) shouldBe false