【问题标题】:Can I pass an object's instance method to a method expecting a callback in Scala?我可以将对象的实例方法传递给期望 Scala 中的回调的方法吗?
【发布时间】:2011-01-06 11:20:25
【问题描述】:

假设我有一个方法需要另一个方法作为参数。是否可以为该参数发送对象的实例方法?我将如何处理没有参数的方法?

我会写一些伪代码:

void myMethod1(callback<void,int> otherFunc); // imagine a function returning void, and taking a int parameter

void myMethod2(callback<int,void> otherFunc); // function returning void, not taking params

如果我有一个 ArrayList,像这样:

val a = new ArrayList()

我怎样才能将add 方法作为myMethod1 的参数发送,而将size 方法作为myMethod2 的参数发送?

【问题讨论】:

  • 了解并牢记在 Scala 中方法和函数是非常不同的东西,这一点很重要。方法不是一流的实体,但函数是。因此(抛开反射不谈),没有方法将另一个方法作为参数。部分应用程序可以与方法或函数一起使用,并且总是产生一个函数。

标签: scala callback functional-programming


【解决方案1】:

Scala 中函数的类型表示

(Types,To,Pass) => ReturnType

(如果只有一个类型要传递,则可以省略括号),将方法转换为函数以传递给另一个方法的方法是

myObject.myMethod _

所以,把这些放在一起——并注意 Java 类的类型:

scala> def addMySize(adder: Int => Boolean, sizer: () => Int) = adder(sizer())
addMySize: ((Int) => Boolean,() => Int)Boolean

scala> val a = new java.util.ArrayList[Int]()
a: java.util.ArrayList[Int] = []

scala> addMySize(a.add _, a.size _)
res0: Boolean = true

scala> addMySize(a.add _, a.size _)
res1: Boolean = true

scala> println(a)
[0, 1]

(请注意,ArrayList 有一个 add,它接受一个对象并返回一个布尔值——而不是一个返回 void 的值。)

【讨论】:

    【解决方案2】:

    我认为myMethod4 可能就是您所说的:“难道不能引用 a.size 并在需要时调用它吗?”。

    def myMethod1(f: Int => Unit): Unit = f(1)
    
    def myMethod2(f: () => Int): Unit = {
      val value = f // f is function, taking no arguments, and returning an int.
                    // we invoke it here.
      ()
    }
    
    def myMethod3(f: => Int): Unit = {
      val value = f // f is call by name parameter.
      ()
    }
    
    def myMethod4[A](f: A => Int, a: A): Unit = {
      val value = f(a)
      ()
    }
    
    import java.util.ArrayList
    
    val a = new ArrayList[Int](1)
    myMethod1((i: Int) => a.add(i))
    myMethod1(a.add(_))     // shorthand for the above
    myMethod2(() => a.size) // a.size is not evaluated, it is enclosed in an anonymous function definition.
    myMethod3(a.size)       // a.size is not evaluated here, it is passed as a by-name parameter.
    myMethod4((al: ArrayList[Int]) => al.size, a)
    myMethod4((_: ArrayList[Int]).size, a)
    myMethod4[ArrayList[Int]](_.size, a)
    

    【讨论】:

    • 你能解释一下空括号在 method2/3/4 中是如何工作的吗?
    • {a; b; c} 必须包含一系列表达式和声明(var、val、class、function、trait、object)。它必须以表达式结尾。为清楚起见,我将 f 的结果分配给了 val value,因此我需要在其后面加上一个符合预期块类型的表达式,在本例中是函数的声明类型:@ 987654326@。 ()Unit 类型的唯一实例。空的return 也可以。与任何其他类型的表达式一样,任何值都可以转换为类型Unit
    【解决方案3】:
    def myMethod(callback : Int => Unit, size : => Int) = ...
    
    myMethod(a.add _, a.size)
    

    Void 通过Unit 类型表示。

    编辑:通过上面对=&gt; Int 的使用,size 通过名称传递,这意味着它总是在需要时重新评估。

    【讨论】:

    • 难道不能引用a.size 并在需要时调用它吗?
    • 您的意思是按名称传递 size:Int 吗? def myMethod(callback: Int => Unit, size: => Int)
    猜你喜欢
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 2016-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多