Scala:方法重载泛型类型

时间:2011-02-13 05:10:04

标签: generics scala manifest reification

在C#中,我可以重载泛型类型的方法,如下例所示:

// http://ideone.com/QVooD
using System;
using System.Collections.Generic;

public class Test {
  public static void Foo(List<int> ints) {
    Console.WriteLine("I just print");
  }

  public static void Foo(List<double> doubles) {
    Console.WriteLine("I iterate over list and print it.");
    foreach(var x in doubles)
      Console.WriteLine(x);
  }

  public static void Main(string[] args) {
    Foo(new List<int> {1, 2});
    Foo(new List<double> {3.4, 1.2});
  }
}

但是,如果我尝试在Scala中执行相同操作,则会由于擦除而将List[Int]List[Double]擦除的编译时错误提升为相同类型。我听说Scala的Manifest可以用来解决这个问题,但我不知道怎么做。我也没有在文档中找到任何有用的东西。

所以我的问题是:如何使用Manifest(或其他有效的方法)来重载方法,而不是因擦除而擦除相同类型的泛型类型?

3 个答案:

答案 0 :(得分:22)

清单不会真正帮助,因为擦除后它们将具有相同的类型。

什么有助于拥有不同数量的参数(或擦除后的不同类型)。我发现有不同数量的隐式参数可以透明地解决这个问题,并且通过使用scala.Predef.DummyImplicit,您甚至不必在任何地方导入隐式参数。

class Test{
  def foo(ints : List[Int])
  def foo(doubles : List[Double])(implicit i1:DummyImplicit)
  def foo(strings : List[String])(implicit i1:DummyImplicit, i2:DummyImplicit)
}

答案 1 :(得分:10)

你不会像Scala中那样做。为什么尝试模拟在JVM限制下永远无法正常工作的东西?尝试使用惯用的Scala:

trait Fooable[T] {
  def foo : Unit
}

object IntListFoo extends Fooable[List[Int]] {
  def foo {
    println("I just print")
  }
}

class DoubleListFoo(val l : List[Double]) extends Fooable[List[Double]] {
  def foo {
    println("I iterate over list and print it.")
    l.foreach { e =>
      println(e)
    }
  }
}

implicit def intlist2fooable(l : List[Int]) = IntListFoo
implicit def doublelist2fooable(l : List[Double]) = new DoubleListFoo(l)

然后,您可以执行

之类的代码
List(1,2,3,4).foo
List(1.0,2.0,3.0).foo

答案 2 :(得分:3)

有点hackish,两种方法都需要相同的返回类型(这里:单位)......

def fooInt(list: List[Int]) = println("int")
def fooDouble(list: List[Double]) = println("double")

def foo[N <: AnyVal](list:List[N])(implicit m:ClassManifest[N]) = m.erasure match {
    case c if c == classOf[Int] => fooInt(list.asInstanceOf[List[Int]])
    case c if c == classOf[Double] => fooDouble(list.asInstanceOf[List[Double]])
    case _ => error("No soup for you!")
}

foo(List(1,2,3,4))
//--> int

foo(List(1.0,2.0,3.0))
//--> double