我有两个案例类
abstract class MainClass
case class Acc(x:String, y:String) extends MainClass
case class Bcc(x:String, y:String) extends MainClass
Run Code Online (Sandbox Code Playgroud)
我需要编写一个通用函数,它将使用其中一个并返回相同案例类的列表,类似于:
def f1[T <: MainClass ]():List[T]={
val o1 = new Acc("sss","ddd").asInstanceOf[T]
List(o1)
}
Run Code Online (Sandbox Code Playgroud)
唯一的问题是我正在对类型类"Acc"进行硬编码.我的问题是如何让f1方法实例化泛型类T而不是Acc或Bcc
提前致谢.
Tra*_*own 11
虽然该ClassTag解决方案可能适合您,但依赖于运行时反射是代码味道,它实际上可以让您陷入真正的麻烦.假设你最终得到了一个像这样的新子类(由你或其他人使用你的代码定义):
case class Ccc(x: String, y: String, i: Int) extends MainClass
Run Code Online (Sandbox Code Playgroud)
现在当有人写f1[Ccc]- 并且方法签名中没有任何迹象表明他们不应该 - 他们的程序将在运行时崩溃NoSuchMethodException.
有一种更安全的方式来做这种事情,虽然它需要为你编写一些样板文字,但对于使用你的代码(包括你自己)的人来说,它是透明的.首先,定义一个类型类,描述如何创建某个特定子类的实例MainClass:
trait MainClassFromStrings[T <: MainClass] {
def apply(x: String, y: String): T
}
Run Code Online (Sandbox Code Playgroud)
然后你写一些类型类实例:
implicit def AccFromStrings: MainClassFromStrings[Acc] =
new MainClassFromStrings[Acc] {
def apply(x: String, y: String) = Acc(x, y)
}
implicit def BccFromStrings: MainClassFromStrings[Bcc] =
new MainClassFromStrings[Bcc] {
def apply(x: String, y: String) = Bcc(x, y)
}
Run Code Online (Sandbox Code Playgroud)
现在你可以写f1得很干净:
def f1[T <: MainClass](implicit fs: MainClassFromStrings[T]) =
List(fs("sss", "ddd"))
Run Code Online (Sandbox Code Playgroud)
然后:
scala> f1[Acc]
res0: List[Acc] = List(Acc(sss,ddd))
scala> f1[Bcc]
res1: List[Bcc] = List(Bcc(sss,ddd))
Run Code Online (Sandbox Code Playgroud)
但是如果你尝试的话,你会得到一个很好的编译时错误f1[Ccc].
类型类在Scala中被广泛使用(包括在标准库中) - 搜索Stack Overflow "type classes" in Scala将会出现大量示例和讨论.
| 归档时间: |
|
| 查看次数: |
371 次 |
| 最近记录: |