首页 文章

Scala中的apply函数是什么?

提问于
浏览
260

我从来没有从设计的解组和修饰名词中理解它(一个 AddTwo 类有一个 apply ,它增加了两个!)的例子 .

我理解它是语法糖,所以(我从上下文推断)它必须设计成使一些代码更直观 .

具有 apply 函数的类有什么意义?它用于什么,以及它使代码变得更好的目的(解组,修改名词等)?

在伴侣对象中使用时如何帮助?

3 回答

  • 38

    它来自于您经常想要将某些东西应用于对象的想法 . 更准确的例子是工厂之一 . 如果您有工厂,则需要将参数应用于它以创建对象 .

    Scala家伙认为,因为它在很多情况下都会发生,所以有一个快捷方式可以调用 apply . 因此,当您直接向对象提供参数时,它就像将这些参数传递给该对象的apply函数一样:

    class MyAdder(x: Int) {
      def apply(y: Int) = x + y
    }
    
    val adder = new MyAdder(2)
    val result = adder(4) // equivalent to x.apply(4)
    

    它经常在伴侣对象中使用,为类或特征提供一个很好的工厂方法,这是一个例子:

    trait A {
      val x: Int
      def myComplexStrategy: Int
    }
    
    object A {
      def apply(x: Int): A = new MyA(x)
    
      private class MyA(val x: Int) extends A {
        val myComplexStrategy = 42
      }
    }
    

    从scala标准库中,您可能会看到如何实现 scala.collection.SeqSeq 是一个特征,因此 new Seq(1, 2) 将无法编译,但是由于伴随对象和apply,您可以调用 Seq(1, 2) 并且伴随对象选择实现 .

  • 556

    数学家有他们自己的小搞笑方式,所以不要说“然后我们称函数 fx 作为参数" as we programmers would say, they talk about "将函数 f 应用于其参数 x ” .

    在数学和计算机科学中,Apply是一个将函数应用于参数的函数 . 维基百科

    apply 用于缩小Scala中面向对象和功能范例之间的差距 . Scala中的每个函数都可以表示为一个对象 . 每个函数也有一个OO类型:例如,一个带有 Int 参数并返回 Int 的函数将具有 Function1[Int,Int] 的OO类型 .

    // define a function in scala
     (x:Int) => x + 1
    
     // assign an object representing the function to a variable
     val f = (x:Int) => x + 1
    

    由于Scala中的所有内容都是对象 f 现在可以将其视为对 Function1[Int,Int] 对象的引用 . 例如,我们可以调用从 Any 继承的 toString 方法,这对于纯函数来说是不可能的,因为函数没有方法:

    f.toString
    

    或者我们可以通过在 f 上调用 compose 方法并将两个不同的函数链接在一起来定义另一个 Function1[Int,Int] 对象:

    val f2 = f.compose((x:Int) => x - 1)
    

    现在,如果我们想要实际执行该函数,或者如数学家所说"apply a function to its arguments",我们将在 Function1[Int,Int] 对象上调用 apply 方法:

    f2.apply(2)
    

    每次要执行表示为对象的函数时写入 f.apply(args) 都是面向对象的方式,但是会在不添加太多额外信息的情况下为代码添加很多混乱,并且能够使用更多标准符号会很好,例如 f(args) . 这就是Scala编译器的步骤,每当我们有一个函数对象的引用 f 并写入 f (args) 以将参数应用于所表示的函数时,编译器会静默地将 f (args) 扩展为对象方法调用 f.apply (args) .

    Scala中的每个函数都可以被视为一个对象,它也可以用于其他方式 - 只要它具有 apply 方法,每个对象都可以被视为一个函数 . 这些对象可以在函数表示法中使用:

    // we will be able to use this object as a function, as well as an object
    object Foo {
      var y = 5
      def apply (x: Int) = x + y
    }
    
    
    Foo (1) // using Foo object in function notation
    

    当我们想要将对象视为函数时,有许多用例 . 最常见的情况是factory pattern . 我们可以使用工厂方法对代码添加混乱,而不是使用一组参数来创建关联类的新实例:

    List(1,2,3) // same as List.apply(1,2,3) but less clutter, functional notation
    
    // the way the factory method invocation would have looked
    // in other languages with OO notation - needless clutter
    List.instanceOf(1,2,3)
    

    所以 apply 方法只是缩小Scala中函数和对象之间差距的一种方便方法 .

  • 5

    对于那些想要快速阅读的人来说,这是一个小例子

    object ApplyExample01 extends App {
    
    
      class Greeter1(var message: String) {
        println("A greeter-1 is being instantiated with message " + message)
    
    
      }
    
      class Greeter2 {
    
    
        def apply(message: String) = {
          println("A greeter-2 is being instantiated with message " + message)
        }
      }
    
      val g1: Greeter1 = new Greeter1("hello")
      val g2: Greeter2 = new Greeter2()
    
      g2("world")
    
    
    }
    

    输出一个greeter-1正在用消息hello实例化一个greeter-2正在用消息世界实例化

相关问题