Scala: перегрузка метода по универсальным типам - PullRequest
10 голосов
/ 13 февраля 2011

В 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] стираются до одного и того же типа из-за стирания. Я слышал, что Manifest можно использовать в Scala, но я не знаю как. Я также не нашел ничего полезного в документах.

Итак, мой вопрос: как я могу использовать Manifest s (или что-то еще, что работает), чтобы перегрузить методы для универсальных типов, которые стираются в тот же тип из-за стирания?

Ответы [ 3 ]

22 голосов
/ 13 февраля 2011

Манифест на самом деле тоже не поможет, потому что те будут иметь тот же тип после стирания.

Что поможет иметь разное количество аргументов (или разные типы после стирания). Я считаю, что разное количество неявных аргументов может прозрачно решить эту проблему, и, используя 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)
}
10 голосов
/ 14 февраля 2011

Вы бы не сделали это так в 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 голосов
/ 13 февраля 2011

Хинди, и оба метода нуждаются в одном и том же типе возврата (здесь: Unit) ...

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...