【问题标题】:Scala: Method overloading over generic typesScala:泛型类型的方法重载
【发布时间】:2011-06-26 08:03:43
【问题描述】:

在 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 的 Manifests 可以用来解决这个问题,但我不知道如何。我在文档中也没有发现任何有用的东西。

所以我的问题是:我如何使用Manifests(或其他任何有效的方法)来重载由于擦除而擦除为相同类型的泛型类型的方法?

【问题讨论】:

  • 实际上,我可能想收回那次近距离投票:引用的问题有一个额外的问题,即某些解决方案只是巧合地起作用,因为其中一种类型是具有两个泛型的元组列表。您可以从 cmets 中找出适用于该版本问题的解决方案,但要弄清楚到底发生了什么需要大量工作。

标签: generics scala manifest reification


【解决方案1】:

Manifest 也无济于事,因为它们在擦除后将具有相同的类型。

什么将有助于拥有不同数量的参数(或擦除后的不同类型)。我发现使用不同数量的隐式参数可以透明地解决这个问题,并且通过使用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)
}

【讨论】:

    【解决方案2】:

    你不会在 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
    

    【讨论】:

      【解决方案3】:

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

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-08
        • 2012-06-05
        • 2011-11-13
        • 2012-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多