我需要编写一个泛型类,它只允许使用Long,Double类型代替[V]
class DummyGenericClass[V](data:Seq[V])
此外,将根据类型存在实施差异。我想做像
这样的事情val typ = if (V is Long) "x" else "y"
编写此类代码的scala建议/最佳做法是什么?
答案 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)))