2015-11-03 165 views
4

传递函数由于Java 8我可以通过这一翻译的在斯卡拉

xyz.foreach(e -> System.out.println(e)); 

我可以做

xyz.foreach(System.out::println) 

我见过this thread有关方法的引用是如何工作的下面,但问题是以下:

Error:(16, 63) ambiguous reference to overloaded definition,

both method toJson in object IanesJsonHelper of type (source: IanesServer)String

and method toJson in object IanesJsonHelper of type (success: Boolean)String

match expected type Function[?,String]

val json = IanesJsonHelper.toJson(array,IanesJsonHelper.toJson _) 

                 ^

我确实有3个函数名为“toJSON”

def toJson(id: Int): String 

def toJson(success: Boolean): String 

def toJson(source: IanesServer): String 

最后一个是正确的。

我在上述错误消息调用函数是:

def toJson[T](source: Array[T], toJson: Function[T, String]): String 

这是相关代码:

val array = new Array[IanesServer](1) 
array(0) = new IanesServer(1, "http://localhost:4567/", "Test") 
val json = IanesJsonHelper.toJson(array,IanesJsonHelper.toJson) 

我没有得到什么我的错误是:

  1. 该阵列属于IanesServer
  2. T在调用方法中, d是IanesServer(Array [IanesServer] - > Array [T]
  3. 由于2.函数中的T必须与数组中的T相同,因此必须是Function [IanesServer,String] - > Function [T,字符串]

有人能指出错误吗?目前我强烈反对,该函数是[?,String]。有任何想法吗?

答: 感谢您的快速答案,这里是我选择:

IanesJsonHelper.toJson[IanesServer](array,IanesJsonHelper.toJson) 

回答

5
def toJson[T](source: Array[T], toJson: Function[T, String]): String 

您预期的编译器来推断toJsonFunction[IanesServer, String]类型的,因为sourceArray[IanerServer]型 - 因此T等于IanesServer

不幸的是,scala编译器不是那么聪明。有两种方法可以帮助这里的编译器:

  1. 国家的类型明确

    IanesJsonHelper.toJson[IanesServer](array, IanesJsonHelper.toJson _)

  2. 斯普利特参数为两个参数列表:

    def toJson[T](source: Array[T])(toJson: Function[T, String]): String 
    
    IanesJsonHelper.toJson(array)(IanesJsonHelper.toJson) 
    

当你有两个参数列表时,参数传递给冷杉t列表将告诉编译器如何绑定T,并且编译器将使用那些绑定作为剩余列表。

下面是另一个短例如:

// doesn't compile - the compiler doesn't realize `_` is an Int and therefore doesn't know about the `+` operator 
def map[A, B](xs: List[A], f: A => B) = ??? 
map(List(1,2,3), _ + 1) 

//compiles fine 
def map[A, B](xs: List[A])(f: A => B) = ??? 
map(List(1,2,3))(_ + 1) 

此行为可能看似不幸的,但有它的一个原因。

与Java或C#不同,Scala使用函数参数列表中的所有参数来计算它们的LUB(最小上界)并使用它来推断函数的泛型类型参数。

例如:

scala> def f[A](x: A, y: A): A = x 
f: [A](x: A, y: A)A 

scala> f(Some(1), None) 
res0: Option[Int] = Some(1) 

在此,使用阶既参数(类型Some[Int]None)来推断的AOption[Int] - 的LUB)类型。这就是为什么scala需要你告诉你指的是toJson哪个超载。

另一方面,C#wouldn't allow this。最后

Compilation error (line 17, col 3): The type arguments for method 'Program.F(T, T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

一个注意:履冰是真棒,但也提出了disadvantages

+0

这很糟糕,Scala编译器不是那么聪明。足够。事情是,那(2)不起作用(IntelliJ抱怨,没有任何方法具有这种Siigneture)。 现在我正在使用“IanesJsonHelper.toJson [IanesServer](array,IanesJsonHelper.toJson)”。非常感谢! PS:感谢您编辑你的文章很多次:)有助于使事情更清晰(坦率地说,没有讽刺) –

+1

@ Reisi007我知道,对吧?这对我来说也是令人惊讶的,尤其是来自C#的背景,在这里可以编译。尽管这个小小的怪癖,我仍然会选择Scala对C#的任何一天的类型推断。 – dcastro

+0

我来自Java,并没有任何问题..(我猜,没有测试)。我只是习惯了Scala。无论如何感谢您的快速回答。非常appriciated:D –