如何创建一个通用的Scala函数,该函数根据泛型类型返回一个对象?

7

(Scala初学者问题)

我正在尝试使用Scala编写一个程序,对C ++源文件进行多项检查,并希望实现可选的检查日志记录。

以下代码适用于单个检查项目:

  val headerFiles = files.filter(_.matches(".*?\\.h$"))
  val headerGuardChecker = if(options.contains('verbose)) {
    new HeaderGuard with LoggingFileCheckerTrait
  } else {
    new HeaderGuard
  } 
  headerFiles.foreach(h => if (! headerGuardChecker.check(new File(h))) println(h + " doesn't have a header guard"))

然而,当我尝试使用泛型来概括这个问题时:
  def checker[T] = if(options.contains('verbose)) {
    new T with LoggingFileCheckerTrait
  } else {
    new T
  } 
  val headerFiles = files.filter(_.matches(".*?\\.h$"))
  headerFiles.foreach(h => if (! checker[HeaderGuard].check(new File(h))) println(h + " doesn't have a header guard"))

我在两个new语句上遇到了编译错误,报告T不是一种类型。我相信这是由于类型擦除引起的,但我还没有找到解决方法。有没有办法实现我想要的功能?


在Scala中,抽象类型和类型参数有什么区别?我尝试了解它们的不同之处,但是仍然感到困惑。谢谢! - James Iry
@JamesIry,你的解决方案没有展示如何创建一个带有TraitXYZ特质的新T。你怎么做到的?或者这是否可能? - Luigi Plinge
1个回答

7

来看一下Scala的“清单”。它们通常可以让你在JVM上规避类型擦除。

scala> def instantiate[T](implicit m:Manifest[T]) = m.erasure.newInstance().asInstanceOf[T]
instantiate: [T](implicit m: Manifest[T])T

scala> instantiate[String]
res0: String = ""

以下是关于Scala中 "manifests" 的优秀介绍:链接

1
请记住,T 可能没有无参构造函数,因此使用 try/catch 可能是个好主意(或者使用反射进行检查)。 - Luigi Plinge
谢谢,这似乎让我克服了那个问题。它仍然没有完全做到我期望的,但至少它可以编译和运行。 - Anthony Berent
实际上我还有一个问题。擦除会丢失特性,所以使用 instantiate[HeaderGuard with LoggingFileCheckerTrait] 给我的结果与使用 instantiate[HeaderGuard] 相同。 - Anthony Berent
同意,说得好。我已经向scala-user提出了这个问题,希望我们能得到权威的答案。在编译时看起来很正常,但在运行时失败这一事实令人不安!http://groups.google.com/group/scala-user/browse_frm/thread/92d02112dbf5e077 - Adam Rabung

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接