如何在scala中编写有界泛型类

时间:2016-12-25 13:16:39

标签: scala generics

我需要编写一个泛型类,它只允许使用Long,Double类型代替[V]

class DummyGenericClass[V](data:Seq[V])

此外,将根据类型存在实施差异。我想做像

这样的事情
val typ = if (V is Long) "x" else "y"

编写此类代码的scala建议/最佳做法是什么?

1 个答案:

答案 0 :(得分:3)

您可以使用密封特征来实现它,这会将可能的实现限制为在同一文件中定义的特征:

sealed trait DummyGenericClass[V] {
  val data: Seq[V]
  val typ: String
}

class LongClass(val data: Seq[Long]) extends DummyGenericClass[Long] {
  val typ = "x"
}

class DoubleClass(val data: Seq[Double]) extends DummyGenericClass[Double] {
  val typ = "y"
}

如果你想拥有DummyGenericClass的通用构造函数,那么类型安全的方法就是使用类型类与工厂模式相结合:

object DummyGenericClass {
  trait Factory[T] {
    def create(seq: Seq[T]): DummyGenericClass[T]
  }

  object Implicits {
    implicit val longProvider = 
      new Factory[Long] {
        def create(seq: Seq[Long]) = new LongClass(seq)
      }

    implicit val doubleProvider =
      new Factory[Double] {
        def create(seq: Seq[Double]) = new DoubleClass(seq)
      }
  }

  def apply[T: Factory](seq: Seq[T]) = implicitly[Factory[T]].create(seq)
}

您可以使用以下方式:

import DummyGenericClass.Implicits._

val foo = DummyGenericClass(Seq.empty[Long])
val bar = DummyGenericClass(Seq.empty[Double])

// Won't compile:
val baz = DummyGenericClass(Seq.empty[String])

另一方面,不需要定义类型类来创建DummyGenericClass个实例,就是在工厂方法中将ClassTag绑定到T。但是不推荐使用此解决方案,因为它不是一种类型安全的方法,因为它允许传递不受支持的类型参数,并且在运行时会失败。

如果您想拥有一个使用此构造函数的泛型方法,则必须添加绑定到该方法的DummyGenericClass.Factory上下文:

def add[T: DummyGenericClass.Factory]
    (a: DummyGenericClass[T], b: DummyGenericClass[T]) =
  DummyGenericClass(a.data ++ b.data)

import DummyGenericClass.Implicits._

add(DummyGenericClass(Seq(1.0)), DummyGenericClass(Seq(2.0)))