364 Stimmen

Was ist die apply-Funktion in Scala?

Ich habe es nie verstanden, von den konstruierten unmarshalling und verbing Substantive ( an AddTwo Klasse hat eine apply das sind zwei mehr!) Beispiele.

Soweit ich weiß, handelt es sich dabei um syntaktischen Zucker, der (wie ich aus dem Kontext schließe) entwickelt wurde, um einen Code intuitiver zu machen.

Welche Bedeutung hat eine Klasse mit einem apply Funktion geben? Wofür wird sie verwendet, und für welche Zwecke macht sie den Code besser (Unmarshalling, Verbing Nomen usw.)?

Wie hilft es, wenn es in einem Begleitobjekt verwendet wird?

747voto

Vlad Gudim Punkte 23001

Mathematiker haben ihre eigene Art und Weise, also anstatt zu sagen "dann rufen wir die Funktion f vorbeigehend x als Parameter", wie wir Programmierer sagen würden, sie sprechen von "Funktion anwenden f zu seinem Argument x ".

In der Mathematik und der Informatik ist "Anwenden" eine Funktion, die Funktionen auf Argumente anwendet.
Wikipedia

apply dient dem Zweck, die Lücke zwischen objektorientierten und funktionalen Paradigmen in Scala zu schließen. Jede Funktion in Scala kann als Objekt dargestellt werden. Jede Funktion hat auch einen OO-Typ: zum Beispiel eine Funktion, die ein Int Parameter und gibt eine Int hat den OO-Typ von Function1[Int,Int] .

 // define a function in scala
 (x:Int) => x + 1

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

Da in Scala alles ein Objekt ist f kann nun als ein Verweis auf Function1[Int,Int] Objekt. Zum Beispiel können wir aufrufen toString Methode geerbt von Any Das wäre bei einer reinen Funktion unmöglich gewesen, da Funktionen keine Methoden haben:

  f.toString

Oder wir könnten eine andere Function1[Int,Int] Objekt durch Aufruf von compose Methode auf f und die Verkettung zweier verschiedener Funktionen:

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

Wenn wir nun die Funktion tatsächlich ausführen wollen, oder wie der Mathematiker sagt "eine Funktion auf ihre Argumente anwenden", würden wir die Funktion apply Methode auf der Function1[Int,Int] Objekt:

 f2.apply(2)

Schreiben f.apply(args) jedes Mal, wenn Sie eine Funktion ausführen wollen, die als Objekt dargestellt wird, ist der objektorientierte Weg, würde aber eine Menge Unordnung in den Code bringen, ohne viel zusätzliche Information hinzuzufügen, und es wäre schön, wenn Sie mehr Standardnotation verwenden könnten, wie z.B. f(args) . An dieser Stelle greift der Scala-Compiler ein, und wann immer wir eine Referenz haben f in ein Funktionsobjekt und schreiben f (args) um Argumente auf die dargestellte Funktion anzuwenden, erweitert der Compiler stillschweigend f (args) zum Aufruf der Objektmethode f.apply (args) .

Jede Funktion in Scala kann als Objekt behandelt werden und es funktioniert auch umgekehrt - jedes Objekt kann als Funktion behandelt werden, vorausgesetzt es hat die apply Methode. Solche Objekte können in der Funktionsschreibweise verwendet werden:

// 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 

Es gibt viele Anwendungsfälle, in denen wir ein Objekt als Funktion behandeln möchten. Das häufigste Szenario ist ein Fabrikmuster . Anstatt den Code mit einer Fabrikmethode unübersichtlich zu machen, können wir apply Objekt mit einer Reihe von Argumenten, um eine neue Instanz einer zugehörigen Klasse zu erstellen:

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) 

Also apply Methode ist einfach eine praktische Möglichkeit, die Lücke zwischen Funktionen und Objekten in Scala zu schließen.

65voto

Nicolas Punkte 23971

Es kommt von der Idee, dass man oft anwenden. etwas zu einem Objekt. Das genauere Beispiel ist das der Fabriken. Wenn Sie eine Fabrik haben, wollen Sie anwenden. Parameter an, um ein Objekt zu erstellen.

Scala-Jungs dachten, dass es, da es in vielen Situationen vorkommt, nett sein könnte, eine Abkürzung zum Aufruf von apply . Wenn Sie also Parameter direkt an ein Objekt übergeben, wird es so desugariert, als ob Sie diese Parameter an die apply-Funktion dieses Objekts übergeben:

class MyAdder(x: Int) {
  def apply(y: Int) = x + y
}

val adder = new MyAdder(2)
val result = adder(4) // equivalent to x.apply(4)

Es wird oft in Companion-Objekten verwendet, um eine schöne Factory-Methode für eine Klasse oder einen Trait bereitzustellen, hier ein Beispiel:

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
  }
}

In der Scala-Standardbibliothek können Sie nachsehen, wie scala.collection.Seq umgesetzt wird: Seq ist ein Merkmal, also new Seq(1, 2) wird nicht kompiliert, aber dank Companion Object und Apply können Sie Seq(1, 2) und die Implementierung wird durch das Begleitobjekt gewählt.

17voto

sdinesh94 Punkte 1068

Hier ein kleines Beispiel für diejenigen, die sich schnell einen Überblick verschaffen wollen

 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")

} 

Ausgabe

Ein Greeter-1 wird mit der Nachricht hello instanziiert

Ein Greeter-2 wird mit der Nachrichtenwelt instanziiert

10voto

TLDR für Leute, die von c++

Es ist einfach ein überladener Operator von ( ) Klammern

Also in Scala:

class X {
   def apply(param1: Int, param2: Int, param3: Int) : Int = {
     // Do something
   }
}

Ist dasselbe wie das in C++:

class X {
   int operator()(int param1, int param2, int param3) {
      // do something
   }
};

2voto

jiawei hu Punkte 41

1 - Funktionen als Objekte behandeln.

2 - Die Methode "Anwenden" ist vergleichbar mit __anrufen __ in Python, die es Ihnen ermöglicht, eine Instanz einer bestimmten Klasse als Funktion zu verwenden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X