4

越来越类型消除编译器警告匹配任何人都可以重新编写此代码做同样的事情,但没有任何编译器警告,请: -我怎么能一个函数签名,而不在斯卡拉

object TestTypeErasure { 

    def main(args:Array[String]) { 

    def myFunction(myObject:Any):Boolean = { 
     true 
    } 

    val myVariable: (Any => Boolean) = myFunction 

    myVariable match { 
     case function:(Any => Boolean) => println("Match") 
    } 

    } 
} 

千thankyous

Keith

更新!!!!对不起,这是一个真正的散列。它我的SO

第一个问题,只是为了让大师们知道我已经沿着这个线路也无济于事试过的东西: - (不能编译)

object TestTypeErasure { 

    def doTest(parameter: Any) = { 
     parameter match { 
      case function:Function1[_, _] => function("Whatever") 
     } 
    } 

    def main(args:Array[String]) { 
    } 

} 

我得到错误: -

TestTypeErasure.scala:6: error: type mismatch; 
    found : java.lang.String("Whatever") 
    required: _ 
    case function:Function1[_, _] => function("Whatever") 
               ^
one error found 

再次感谢

基思

回答

0
+0

嗨 我已经采取了看那个。我尝试了最佳答案。接下来的困难是我想调用这个函数。 如果我改变代码来实际调用下面的函数,我得到一个编译器错误。有谁知道我怎么能解决这个 对象TestTypeErasure { 高清doTest(参数:任何)= { 参数匹配{ 情况下功能:功能1 [_,_] =>函数( “什么”) } } 高清主(参数:数组[字符串]){} } 再次感谢 基思 – Keith 2010-01-25 15:42:33

3

您可以使用Manifests捕获类型信息。 (T,R是不变的位置让事情变得简单。)

import scala.reflect._ 
def matchFunction[T,R](f: Function1[T,R], t : T)(implicit mt : Manifest[T], mr : Manifest[R]) = { 
    val result = if ((mt.erasure, mr.erasure) == (classOf[Any], classOf[Boolean])) "any, boolean " + f(t) 
    else if((mt.erasure, mr.erasure) == (classOf[Int], classOf[Int])) "int, int " + f(t) 
    else "Unknown " + f(t) 
    println(result) 
} 

scala>  matchFunction((x : Int) => x + 1, 1) 
int, int 2 

scala>  matchFunction((x : Any) => true, 1 : Any) 
any, boolean true 

scala>  matchFunction((x : Boolean) => ! x, false) 
Unknown 

对于斯卡拉2.8可以使用上下文范围,去掉两个隐含的参数:

import scala.reflect._ 
def matchFunction[T: Manifest,R : Manifest](f: Function1[T,R], t : T) = { 
    val mt = implicitly[Manifest[T]] 
    val mr = implicitly[Manifest[T]] 
    val result = if ((mt.erasure, mr.erasure) == (classOf[Any], classOf[Boolean])) "any, boolean " + f(t) 
    else if((mt.erasure, mr.erasure) == (classOf[Int], classOf[Int])) "int, int " + f(t) 
    else "Unknown " + f(t) 
    println(result) 
} 
+0

只是注意,您需要的Scala 2.8本。 – retronym 2010-01-25 18:18:46

+0

@retronym否,这在2.7.7中有效。 Manifest应该自2.7.2开始提供。 – 2010-01-25 18:35:20

0

有多种方法可能工作,这些都不那么简单。

一个选择是使用清单,但是你必须定义你自己的清单感知的匹配变体。您可以阅读更多关于清单here。如果你必须做很多这样的事情,那将是一条路,尽管这个特征仍然被认为是实验性的。

另一种选择是,如果您的使用量相对较轻,则将该函数包装在某些非通用类中。例如,

object Example { 
    def hasString(a:Any) = (a!=null && a.toString.length>0) 

    case class AnyImpliesBoolean(f: (Any) => Boolean) { } 
    implicit def callAIB(aib: AnyImpliesBoolean) = aib.f 

    def callWrapped(a: Any) { 
    a match { 
     case aib: AnyImpliesBoolean => println(aib("Check")) 
     case _ => println("(Nothing)") 
    } 
    } 

    def tryMe() { 
    val has = AnyImpliesBoolean(hasString _) 
    callWrapped(has) 
    callWrapped("foo") 
    callWrapped((s:String)=>true) 
    } 
} 

scala> Example.tryMe 
true 
(Nothing) 
(Nothing) 

如果你是包装几个不同的功能,但不能太多了,你可以创建一个基类WrappedFunction再有类似的事情扩展AnyImpliesBoolean WrappedFunction。

还有一种选择是实际上不传递函数,而是使用反射来传递java.lang.Methods。方法知道它们的类型。即使有一些漂亮的Scala包装器,它仍然会有点笨重(并且它不是高性能的)。

(编辑补充清单链接我失踪了。)