简体   繁体   English

Scala:方法重载泛型类型

[英]Scala: Method overloading over generic types

In C# I can overload methods on generic type as shown in the example below: 在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});
  }
}

However if I try to do the same in Scala, it will raise a compile time error that List[Int] and List[Double] erase to the same type due to erasure. 但是,如果我尝试在Scala中执行相同操作,则会由于擦除而将List[Int]List[Double]擦除的编译时错误引发到相同类型。 I heard Scala's Manifest s can be used to work around this, but I don't know how. 我听说Scala的Manifest可以用来解决这个问题,但我不知道怎么做。 I didn't find anything helpful in the docs either. 我也没有在文档中找到任何有用的东西。

So my question is: How do I use Manifest s (or whatever else that works) to overload methods over generic types that erase to same type due to erasure? 所以我的问题是:我如何使用Manifest (或其他任何有效的东西)来重载方法而不是因擦除而擦除到相同类型的泛型类型?

The Manifest won't really help either becuase those will have the same type after erasure. 由于擦除后那些将具有相同类型,因此清单不会真正帮助。

What will help having different numbers of arguments (or different types after erasure). 什么将有助于具有不同数量的参数(或擦除后的不同类型)。 I find having different numbers of implicit arguments can transparently solve this problem, and by using scala.Predef.DummyImplicit , you don't even have to import an implicit anywhere. 我发现有不同数量的隐式参数可以透明地解决这个问题,并且通过使用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)
}

You would not do it like that in Scala. 你不会像Scala中那样做。 Why try to emulate something that can never work properly given JVM restrictions? 为什么尝试模拟在JVM限制下永远无法正常工作的东西? Try idiomatic Scala instead: 尝试惯用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)

Then, you can execute code like 然后,您可以执行类似的代码

List(1,2,3,4).foo
List(1.0,2.0,3.0).foo

Kinda hackish, and both methods need the same return type (here: Unit)... 有点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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM