[scala] 스칼라의 적용 기능은 무엇입니까?

나는 고안된 언 마샬링과 동사 명사 ( AddTwo클래스에 apply두 가지를 더한!) 예제 에서 그것을 이해하지 못했습니다 .

나는 그것이 구문 설탕이라는 것을 이해하므로 (나는 문맥에서 추론) 일부 코드를보다 직관적으로 만들도록 설계되어야합니다.

apply함수 가있는 클래스는 어떤 의미를 갖 습니까? 어떤 용도로 사용되며 어떤 목적으로 코드를 개선합니까 (비 정렬 화, 동사 명사 등)?

컴패니언 객체에서 사용될 때 어떻게 도움이됩니까?



답변

수학자들은 자신 만의 재미있는 방법을 가지고 있기 때문에 프로그래머가 말하는 것처럼 ” f그것을 함수 를 x매개 변수로 전달하는 것 “이라고 말하는 대신 ” f인수에 함수 적용 하기 “에 대해 이야기 x합니다.

수학과 컴퓨터 과학에서 Apply는 함수를 인수에 적용하는 함수입니다.
위키 백과

applyScala의 객체 지향 패러다임과 기능 패러다임 사이의 격차를 메우기위한 목적으로 사용됩니다. 스칼라의 모든 기능은 객체로 표현 될 수 있습니다. 모든 함수에는 OO 유형도 있습니다. 예를 들어 Int매개 변수를 사용하고을 반환하는 함수 Int는 OO 유형이 OO입니다 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

모든 것이 스칼라의 객체이기 때문에 f이제 객체에 대한 참조로 취급 될 수 있습니다 Function1[Int,Int]. 예를 들어, 함수에는 메소드가 없기 때문에 순수 함수로는 불가능했던 toString에서 상속 된 메소드 를 호출 할 수 있습니다 Any.

  f.toString

또는 메소드를 Function1[Int,Int]호출 하고 두 개의 다른 함수를 함께 연결 하여 다른 객체를 정의 할 수 있습니다.composef

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

이제 실제로 함수를 실행하거나 수학자가 “인수에 함수 적용”이라고 말하면 객체 에서 apply메소드를 호출 Function1[Int,Int]합니다.

 f2.apply(2)

f.apply(args)객체로 표현 된 함수를 실행할 때마다 쓰는 것은 객체 지향 방식이지만 많은 정보를 추가하지 않고 코드에 많은 혼란을 줄 수 있으며 더 많은 표준 표기법을 사용할 수 있습니다. 로 f(args). Scala 컴파일러가 들어가서 f함수 객체에 대한 참조 가 있고 f (args)표현 된 함수에 인수를 적용하기 위해 쓸 때마다 컴파일러 f (args)는 객체 메소드 호출로 자동 확장 됩니다 f.apply (args).

스칼라의 모든 함수는 객체로 취급 될 수 있으며 다른 방식으로도 작동합니다. 모든 객체는 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 

객체를 함수로 취급하려는 많은 사용 사례가 있습니다. 가장 일반적인 시나리오는 팩토리 패턴 입니다. 팩토리 메소드를 사용하여 코드에 혼란을 추가하는 대신 apply인수 세트에 이의를 제기하여 연관된 클래스의 새 인스턴스를 작성할 수 있습니다.

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메소드는 스칼라에서 함수와 객체 사이의 간격을 좁히는 편리한 방법입니다.


답변

그것은 종종 물체에 무언가를 적용 하고 싶다는 생각에서 비롯 됩니다 . 더 정확한 예는 공장 중 하나입니다. 팩토리가있는 경우 매개 변수를 적용 하여 객체를 작성하려고합니다.

스칼라 녀석은 많은 상황에서 발생하기 때문에을 호출하는 지름길을 갖는 것이 좋을 것이라고 생각했습니다 apply. 따라서 매개 변수를 객체에 직접 제공하면 해당 매개 변수를 해당 객체의 apply 함수에 전달하는 것처럼 desugared됩니다.

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.collection.Seq구현 방법을 살펴볼 수 있습니다 Seq. 특성 new Seq(1, 2)은 컴파일되지 않지만 컴패니언 객체와 적용 덕분에 호출 할 수 Seq(1, 2)있으며 컴패니언 객체가 구현을 선택합니다.


답변

다음은 빠르게 숙달하려는 사람들을위한 작은 예입니다.

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


} 

산출

인사 -1이 메시지 hello로 인스턴스화되고 있습니다.

greeter-2는 메시지 세계와 함께 인스턴스화되고 있습니다


답변