首页 > 解决方案 > 将类型模式加工转换为类型类

问题描述

我有以下代码:

val byteBuffer = array(0) match {
  case _: Int =>
    ByteBuffer.allocate(4 * array.length)
  case _: Long =>
    ByteBuffer.allocate(8 * array.length)
  case _: Float =>
    ByteBuffer.allocate(4 * array.length)
  case _: Double =>
    ByteBuffer.allocate(8 * array.length)
  case _: Boolean =>
    ByteBuffer.allocate(1 * array.length)
}

如何将其转换为使用类型类?

编辑:

有人问我数组的类型是什么。情况很复杂。数组声明如下:

val array = obj.asInstanceOf[mutable.WrappedArray[Any]].array

obj 是函数接受的参数:

val createBuffer = (obj: Any, dType: DataType) => dType match {

该函数在这里调用:

val byteBuffer: Option[ByteBuffer] = createBuffer(row.get(i), types(i))

行是 Spark DataFrame 行。

标签: scalafunctional-programmingpattern-matchingtypeclass

解决方案


一个类型类看起来像这样:

trait ByteSize[T] {
  def tSize: Int
}

object ByteSize {
  implicit final val IntByteSize: ByteSize[Int] =
    new ByteSize[Int] {
      override final val tSize: Int = 4
    }

  implicit final val LongByteSize: ByteSize[Long] =
    new ByteSize[Long] {
      override final val tSize: Int = 8
    }

  // Other instances.
}

object syntax {
  object bytes {
    implicit class ArrayOps[T](private val arr: Array[T]) extends AnyVal {
      final def allocateByteBuffer(implicit ev: ByteBuffer[T]): ByteBuffer =
        ByteBuffer.allocate(ev.tSize * array.length)
    }
  }
}

您可以使用如下:

import syntax.bytes._

val arr: Array[Int] = ???

val byteBuffer = arr.allocateByteBuffer

你甚至可以提供更有用的扩展方法,比如不只是分配ByteBuffer,你可以直接填充它。


注意,记住类型是类型驱动的,因此在编译时被解析。如果您不知道数组的类型,那么该模式匹配是您能做的最好的事情。
你可能想看看你是否可以重构你的代码,让它变成更强的类型,因为Any,一般来说,被认为是代码异味。但是,如果你做不到,或者工作量太大,那么类型类就是不适合这项工作的工具。


推荐阅读