不自然な動詞化された名詞(AddTwo
クラスにはapply
2つ追加された!)の例から、私はそれを理解できませんでした。
私はそれが構文上の砂糖であることを理解しているので、(私はコンテキストから推測して)いくつかのコードをより直観的にするように設計されていたに違いありません。
apply
関数を持つクラスはどのような意味を持ちますか?それは何のために使用され、コードを改善する目的は何ですか(非整列化、動詞の名詞など)?
コンパニオンオブジェクトで使用するとどのように役立ちますか?
不自然な動詞化された名詞(AddTwo
クラスにはapply
2つ追加された!)の例から、私はそれを理解できませんでした。
私はそれが構文上の砂糖であることを理解しているので、(私はコンテキストから推測して)いくつかのコードをより直観的にするように設計されていたに違いありません。
apply
関数を持つクラスはどのような意味を持ちますか?それは何のために使用され、コードを改善する目的は何ですか(非整列化、動詞の名詞など)?
コンパニオンオブジェクトで使用するとどのように役立ちますか?
回答:
数学者は独自の少し面白い方法を持っているので、プログラマーが言うように「それをパラメーターとしてf
渡して関数を呼び出す」と言う代わりに、「引数にx
関数f
を適用する」と話しますx
。
数学とコンピュータサイエンスでは、Applyは引数に関数を適用する関数です。
ウィキペディア
apply
Scalaのオブジェクト指向パラダイムと機能パラダイムの間のギャップを埋める目的を果たします。Scalaのすべての関数はオブジェクトとして表すことができます。すべての関数にはOOタイプもあります。たとえば、Int
パラメーターを受け取ってInt
を返す関数には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
Scalaではすべてがオブジェクトであるため、オブジェクトf
への参照として扱うことができFunction1[Int,Int]
ます。たとえば、toString
から継承されたメソッドを呼び出すAny
ことができますが、関数にはメソッドがないため、純粋な関数では不可能でした。
f.toString
または、メソッドをFunction1[Int,Int]
呼び出して2つの異なる関数をチェーンすることで、別のオブジェクトを定義することもできます 。compose
f
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)
です。
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
オブジェクトを関数として扱いたい場合、多くの使用例があります。最も一般的なシナリオは、ファクトリパターンです。ファクトリメソッドを使用してコードに混乱を追加する代わり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
メソッドはScalaの関数とオブジェクト間のギャップを埋めるのに便利な方法にすぎません。
class Average[YType](yZeroValue:YType)
。このクラスがあります。オブジェクトはタイプパラメータを取得できないため、そのオブジェクトからYTypeをどのように渡しますか?
apply
およびunapply
メソッドします。したがって、このように1行だけでクラスを定義するcase class Car(make:String, model: String, year: Short, color: String)
と、Carクラスの新しいオブジェクトを次のように作成できますval myCar = Car("VW","Golf",1999,"Blue")
。これは省略形ですCar.apply(...)
every object can be treated as a function, provided it has the apply method
-今はとても理にかなっています。
それは、オブジェクトに何かを適用したいことがよくあるという考えから来ています。より正確な例は、工場の1つです。ファクトリーがある場合、それにパラメーターを適用してオブジェクトを作成します。
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.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")
}
出力
greeter-1はメッセージhelloでインスタンス化されています
greeter-2がメッセージの世界でインスタンス化されています