Scala中函数重载的仿真

Scala中函数重载的仿真,scala,implicit,Scala,Implicit,我对Scala编程相当陌生,所以仍然在寻找做某事的标准方法。最近,我想写一个函数foo,它只接受一组类型作为它唯一的参数。想一想 def foo(x: [Int, String]) = ??? 但我找不到任何接近我认为最自然的语法。使用类型Any会丢失编译端检查,使问题更容易转移到运行时环境中 我能想到的最好的办法是: sealed abstract class Base case class TypeInt(v: Int) extends Base case class TypeString

我对Scala编程相当陌生,所以仍然在寻找做某事的标准方法。最近,我想写一个函数foo,它只接受一组类型作为它唯一的参数。想一想

def foo(x: [Int, String]) = ???
但我找不到任何接近我认为最自然的语法。使用类型Any会丢失编译端检查,使问题更容易转移到运行时环境中

我能想到的最好的办法是:

sealed abstract class Base
case class TypeInt(v: Int) extends Base
case class TypeString(v: String) extends Base

implicit def toTypeInt(v: Int) = TypeInt(v)
implicit def toTypeString(v: String) = TypeString(v)

def foo(x: Base) = x match {
  case TypeInt(v) => println("Int: ", v)
  case TypeString(v) => println("String: ", v)
}

foo(1)
foo("hello")
作为旁注,我希望能够编写隐式case类。。。避免手动创建toType*函数,但这不会编译

有没有更简单的方法来编写一个函数,以类型安全的方式接受一组类型的参数


更新:事实证明,在我的特定情况下,我可以使用方法重载。出于某种原因,在Scala工作表中根本不可能使用方法重载,这让我认为Scala根本没有重载。但我错了——在常规Scala源代码中,应该可以使用它。在下面的评论中提到的关于Magnet模式的文章中描述了重载使用的一些缺点,例如,由于JVM泛型中的类型擦除,无法重载类型Foo[Type1]和Foo[Type2]。

Magnet模式感觉像是杀伤力过大。您可以使用普通的旧类型类:

trait Fooable[A] { def apply(a: A): Unit }

implicit object intFooable extends Fooable[Int] {
  def apply(a: Int) = printf("Int: %d\n", a)
}

implicit object stringFooable extends Fooable[String] {
  def apply(a: String) = printf("String: %s\n", a)
}

def foo[A: Fooable](a: A) = implicitly[Fooable[A]].apply(a)
然后:

scala> foo(1)
Int: 1

scala> foo("hello")
String: hello
假设您担心擦除后的冲突。让我们尝试一些泛型类型的实例:

trait Bar[A]

implicit object barIntFooable extends Fooable[Bar[Int]] {
  def apply(a: Bar[Int]) = println("A bar of ints.")
}

implicit object barStringFooable extends Fooable[Bar[String]] {
  def apply(a: Bar[String]) = println("A bar of strings.")
}
再说一遍:

scala> foo(new Bar[Int] {})
A bar of ints.

scala> foo(new Bar[String] {})
A bar of strings.

一切按预期运行。

磁铁模式感觉有些过火。在这里,您可以使用普通的旧类型类:

trait Fooable[A] { def apply(a: A): Unit }

implicit object intFooable extends Fooable[Int] {
  def apply(a: Int) = printf("Int: %d\n", a)
}

implicit object stringFooable extends Fooable[String] {
  def apply(a: String) = printf("String: %s\n", a)
}

def foo[A: Fooable](a: A) = implicitly[Fooable[A]].apply(a)
然后:

scala> foo(1)
Int: 1

scala> foo("hello")
String: hello
假设您担心擦除后的冲突。让我们尝试一些泛型类型的实例:

trait Bar[A]

implicit object barIntFooable extends Fooable[Bar[Int]] {
  def apply(a: Bar[Int]) = println("A bar of ints.")
}

implicit object barStringFooable extends Fooable[Bar[String]] {
  def apply(a: Bar[String]) = println("A bar of strings.")
}
再说一遍:

scala> foo(new Bar[Int] {})
A bar of ints.

scala> foo(new Bar[String] {})
A bar of strings.

一切正常。

您正在尝试重新发明感谢-我将阅读该链接。@AlexeyAlexandrov:您应该将更新移动到一个答案,并接受它以将您的问题标记为已回答。您正在尝试重新发明感谢-我将阅读该链接。@AlexeyAlexandrov:您应该将更新移动到一个答案,并接受它以标记您的答案如所回答的问题。