2012-03-16 16 views
230

मैंने इसे कभी भी अनारक्षित और क्रियात्मक संज्ञाओं से नहीं समझा (AddTwo कक्षा में apply है जो दो जोड़ता है!) उदाहरण।स्कैला में लागू फ़ंक्शन क्या है?

मैं समझता हूं कि यह वाक्य रचनात्मक चीनी है, इसलिए (मैंने संदर्भ से घटाया) इसे कुछ कोड अधिक सहज बनाने के लिए डिज़ाइन किया गया होगा।

apply फ़ंक्शन वाली कक्षा का क्या अर्थ है? इसके लिए क्या उपयोग किया जाता है, और यह कौन सा उद्देश्य कोड को बेहतर बनाता है (unmarshalling, संज्ञा संज्ञा आदि)?

किसी साथी ऑब्जेक्ट में उपयोग किए जाने पर यह कैसे मदद करता है?

+4

यहां तक ​​कि एक त्वरित googling भी बहुत सारे लाता है अच्छा लेख यहां एक है: http://jackcoughonsoftware.blogspot.com/2009/01/deeper-look-at-apply-method-in-scala.html –

+0

http://stackoverflow.com/questions/1223834/how-does- स्केलस-लागू-विधि-जादू-कार्य – ses

+4

वास्तव में यह जावा/सी ++ में एक निर्माता के समान है लेकिन मान वापस कर सकता है और 'लागू' नाम – ses

उत्तर

508

गणितज्ञ तो बजाय कहा, "तो हम गुजर समारोह f फोन यह x एक पैरामीटर के रूप में" अपने स्वयं के छोटे से अजीब तरीके हैं, जैसा कि हम कह सकते हैं कि प्रोग्रामर, वे "अपने तर्क x को समारोह f लागू करने" के बारे में बात करते हैं।

गणित और कंप्यूटर विज्ञान में, लागू एक ऐसा फ़ंक्शन है जो तर्कों के लिए फ़ंक्शन लागू करता है।
Wikipedia

apply स्काला में वस्तु उन्मुख और कार्यात्मक मानदंड के बीच की खाई को बंद करने के उद्देश्य में कार्य करता। स्कैला में प्रत्येक कार्य को एक वस्तु के रूप में दर्शाया जा सकता है। प्रत्येक फ़ंक्शन में ओओ प्रकार भी होता है: उदाहरण के लिए, एक फ़ंक्शन जो Int पैरामीटर लेता है और Int देता है ओओ प्रकार 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 

या हम f पर compose विधि को फोन करके एक और Function1[Int,Int] वस्तु निर्धारित कर सकते हैं और दो अलग अलग कार्यों को एक साथ चेनिंग:

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

अब अगर हम वास्तव में समारोह निष्पादित करने के लिए चाहते हैं, या गणितज्ञ के रूप में कहते हैं कि "अपने तर्कों को एक समारोह लागू" हमपर apply विधि कहेंगेवस्तु:

f2.apply(2) 

f.apply(args) हर बार जब आप एक समारोह एक वस्तु के रूप में प्रतिनिधित्व पर अमल करना चाहते लेखन वस्तु उन्मुख तरीका है, लेकिन ज्यादा अतिरिक्त जानकारी के जोड़े बिना कोड के लिए अव्यवस्था का एक बहुत जोड़ना होगा और यह होगा f(args) जैसे अधिक मानक नोटेशन का उपयोग करने में सक्षम होना अच्छा है। यही वह जगह है जहां स्कैला कंपाइलर कदम उठाता है और जब भी हमारे पास फ़ंक्शन ऑब्जेक्ट में f संदर्भ होता है और प्रस्तुति फ़ंक्शन पर तर्क लागू करने के लिए f (args) लिखता है तो संकलक चुपचाप ऑब्जेक्ट विधि कॉल f.apply (args) पर f (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 

कई उपयोग मामलों रहे हैं जब हम एक समारोह के रूप में एक वस्तु के इलाज के लिए चाहते हैं। सबसे आम परिदृश्य 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 विधि बस के बीच की खाई को बंद करने के एक आसान तरीका है: इसके बजाय तर्क का एक सेट करने के लिए एक कारखाने विधि हम apply वस्तु कर सकते हैं का उपयोग कर एक संबद्ध वर्ग का एक नया उदाहरण बनाने के लिए कोड के लिए अव्यवस्था को जोड़ने का स्कैला में कार्य और वस्तुओं।

+1

आप किसी ऑब्जेक्ट में कस्टम चर प्रकार कैसे जोड़ देंगे। AFAIK यह संभव नहीं है। यहां एक उदाहरण दिया गया है: आपके पास इस वर्ग की कक्षा औसत [वाईटी टाइप] (yZeroValue: YType) 'है। आप YType को इसके ऑब्जेक्ट से कैसे पास करते हैं क्योंकि ऑब्जेक्ट टाइप पैरा नहीं ले सकते हैं? – Adrian

+0

स्कैला में प्रकार आमतौर पर तर्कों के आधार पर अनुमान लगाया जा सकता है, लेकिन यदि आप उन्हें स्क्वायर ब्रैकेट के माध्यम से आपूर्ति नहीं कर सकते हैं। इसलिए जब औसत ऑब्जेक्ट को तुरंत चालू किया जा सकता है तो आप कह सकते हैं "val avg = new average [int] (0)" –

+3

केस क्लास यहां उल्लेखनीय हैं। केस कक्षाएं आसानी से, स्वचालित रूप से और अदृश्य रूप से कक्षा के एक साथी वस्तु (अन्य चीजों के साथ) 'लागू' और 'अनुपयोगी' विधियों को जोड़ती हैं। तो इस श्रेणी की कार कार (मेक: स्ट्रिंग, मॉडल: स्ट्रिंग, वर्ष: शॉर्ट, रंग: स्ट्रिंग) जैसी सिर्फ एक पंक्ति के साथ एक वर्ग को परिभाषित करना, 'कार वर्ग की नई वस्तुओं को केवल तभी बनाना संभव बनाता है:' val myCar = कार ("VW", "गोल्फ", 1999, "ब्लू") '। यह 'Car.apply (...)' –

37

यह इस विचार से आता है कि आप अक्सर किसी ऑब्जेक्ट पर लागू करना चाहते हैं। कारखानों में से एक सटीक उदाहरण है। जब आपके पास कोई कारखाना होता है, तो आप ऑब्जेक्ट बनाने के लिए पैरामीटर लागू करना चाहते हैं।

स्कैला लोगों ने सोचा कि, जैसा कि यह कई स्थितियों में होता है, 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) पर कॉल कर सकते हैं और कार्यान्वयन साथी द्वारा चुना जाता है आयन वस्तु।

+0

लागू करने के बराबर इम्प्लिकिट्स का उपयोग करके पूरा किया जा सकता है? – jayunit100

3

यहाँ जो लोग पढ़ने के लिए चाहते हैं के लिए एक छोटा सा उदाहरण है जल्दी से

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 संदेश के साथ instantiated की जा रही है हैलो

एक स्वागतकर्ता -2 किया जा रहा है संदेश की दुनिया के साथ तत्काल

+0

के लिए शॉर्टेंड है g2 सही के लिए संदेश है? क्या यह वास्तव में तत्कालता पर हो रहा है, या वास्तव में यह तत्कालता के बाद है (भले ही यह आलसी तत्काल हो)? –

संबंधित मुद्दे