我有两个类,其中包含一些数据成员:
class MyInfo {
private val myId: String
private val time: DateTime
private val solution: Long
private val banner: Int
}
Class HisInfo {
private val id: String
private val solution: Long
private val banner: Int
}
正如您所看到的,这两个类共享两个成员,而在我的真实项目中,它们共享更多。我需要将它们保存到hbase中并设计一个这样的类:
sealed trait Element[T] {
def serialize(value: T)(implicit val helper: Helper[T]): Array[Byte]
def deserialize(bytes: Array[Byte])(implicit val helper: Helper[T]): T
}
case object LongElement extends Element[Long] {...}
case object IntElement extends Element[Int] {...}
class Info {
protected val data: Map[Element[_], Any] = new mutable.Map[Element[_], Any]()
}
class MyInfo extends Info {
val elements = List(LongElement, IntLement)
def saveToHBase = {
elements.foreach { e =>
val v = e.serialize(data(e))
// do sth with v
}
}
实际上我已经定义了Helper [Int]和Helper [Long]的实现,但是编译器抱怨它找不到参数Helper [_1]的隐含值。有人可以帮我设计这些课程吗?
答案 0 :(得分:0)
实际上我已经定义了Helper [Int]和Helper [Long]的实现,但是编译器抱怨它找不到参数Helper [_1]的隐含值。
好吧,考虑如果elements
包含Element[String]
(或其他没有隐式Helper
的类型)会发生什么。鉴于elements
的类型,编译器无法知道它没有。
我认为,无论如何,如果您需要Helper
所有Element
方法,那么您应该将其作为该类型的一部分:
sealed trait Element[T] {
val helper: Helper[T] // or def if you want to put it in the companion object
def serialize(value: T): Array[Byte]
def deserialize(bytes: Array[Byte]): T
}
或
sealed abstract class Element[T](implicit val helper: Helper[T]) {
def serialize(value: T): Array[Byte]
def deserialize(bytes: Array[Byte]): T
}
至少在大多数情况下。
答案 1 :(得分:0)
对于shapeless来说,这看起来很像。{
关于无形的很酷的事情,它可以将你的类转换为名为HList
的结构列表
像List
这样的Scala普通集合应该删除有关元素的信息,以使它们成为普通类型
HList
可以保存每个元素的类型,同时提供List
- 类似功能
让我们用单独的类型
中的公共字段来定义您的类型import org.joda.time.DateTime
class Common(
val solution: Long,
val banner: Int
)
class MyInfo(
myId: String,
time: DateTime,
solution: Long,
banner: Int
) extends Common(solution, banner)
class HistInfo(
id: String,
solution: Long,
banner: Int
) extends Common(solution, banner)
现在让我们定义类似于序列化的东西:
trait Helper[T] extends (T => Array[Byte])
implicit object longHelper extends Helper[Long] {
def apply(x: Long) = 0 to 7 map (i => (x >> (i * 8)).toByte) toArray
}
implicit object intHelper extends Helper[Int] {
def apply(x: Int) = 0 to 3 map (i => (x >> (i * 8)).toByte) toArray
}
现在有趣了。我们将创建一个特殊对象,可以将您的Common
类型转换为特殊HList
,其中包含保留其类型信息的每个值以及具有字段名称的静态保存字符串:
import shapeless._
val lgen = LabelledGeneric[Common]
接下来,我们定义了类似于函数的特殊事物来映射这样的HList
。它会找到已知implicit Helper
并将其结果与相应的字段名称相关联:
import shapeless.labelled.FieldType
object serialized extends Poly1 {
implicit def serialize[K <: Symbol, T]
(implicit helper: Helper[T], key: Witness.Aux[K])
= at[FieldType[K, T]](field => key.value.name -> helper(field))
}
现在我们定义了这个函数的一些用户:
def extractMap(x: Common): Map[String, Seq[Byte]] =
lgen.to(histInfo).map(serialized).toList.toMap.mapValues(_.toSeq)
您可以验证您的功能是否有效:
val histInfo = new HistInfo("123", 12, 3)
println(extractMap(histInfo))
将打印
地图(解决方案 - &gt; WrappedArray(12,0,0,0,0,0,0,0),横幅 - &gt; WrappedArray(3,0,0,0))