खोज…


वाक्य - विन्यास

  • निहित वैल x: टी = ???

टिप्पणियों

इंप्लिक्ट क्लासेस अपने कोड को संशोधित किए बिना, कस्टम तरीकों को मौजूदा प्रकारों में जोड़ने की अनुमति देते हैं, जिससे कोड के नियंत्रण की आवश्यकता के बिना प्रकारों को समृद्ध किया जा सकता है।

किसी मौजूदा वर्ग को समृद्ध करने के लिए निहित प्रकारों का उपयोग करना अक्सर 'मेरे पुस्तकालय को समृद्ध करने' के रूप में संदर्भित किया जाता है।

निहित वर्गों पर प्रतिबंध

  1. निहित वर्ग केवल किसी अन्य वर्ग, वस्तु या विशेषता के भीतर ही मौजूद हो सकते हैं।
  2. निहित वर्गों में केवल एक गैर-निहित प्राथमिक कंस्ट्रक्टर पैरामीटर हो सकता है।
  3. हो सकता है कि एक ही वस्तु, वर्ग, विशेषता या वर्ग सदस्य परिभाषा एक ही दायरे के भीतर न हो जिसमें निहित वर्ग के समान नाम हो।

अव्यवस्थित रूपांतरण

एक अंतर्निहित रूपांतरण संकलक को एक प्रकार की वस्तु को दूसरे प्रकार में स्वचालित रूप से परिवर्तित करने की अनुमति देता है। यह कोड को किसी ऑब्जेक्ट को किसी अन्य प्रकार के ऑब्जेक्ट के रूप में व्यवहार करने की अनुमति देता है।

case class Foo(i: Int)

// without the implicit
Foo(40) + 2    // compilation-error (type mismatch)

// defines how to turn a Foo into an Int
implicit def fooToInt(foo: Foo): Int = foo.i

// now the Foo is converted to Int automatically when needed
Foo(40) + 2    // 42

रूपांतरण एक तरफ़ा है: इस मामले में आप 42 को Foo(42) वापस नहीं बदल सकते। ऐसा करने के लिए, एक दूसरे निहितार्थ को परिभाषित किया जाना चाहिए:

implicit def intToFoo(i: Int): Foo = Foo(i)

ध्यान दें कि यह वह तंत्र है जिसके द्वारा एक फ्लोट मान को पूर्णांक मान में जोड़ा जा सकता है, उदाहरण के लिए।

आरोपित रूपांतरणों को संयम से इस्तेमाल किया जाना चाहिए क्योंकि वे जो कुछ भी हो रहा है उसे बाधित करते हैं। यह एक विधि कॉल के माध्यम से एक स्पष्ट रूपांतरण का उपयोग करने के लिए सबसे अच्छा अभ्यास है जब तक कि एक अंतर्निहित रूपांतरण का उपयोग करने से एक ठोस पठनीयता हासिल न हो।

निहित रूपांतरणों का कोई महत्वपूर्ण प्रदर्शन प्रभाव नहीं है।

स्काला स्वचालित रूप से scala.Predef में कई तरह के निहितार्थ रूपांतरणों को आयात करता है, जिसमें जावा से स्काला और बैक के सभी रूपांतरण शामिल हैं। ये किसी भी फ़ाइल संकलन में डिफ़ॉल्ट रूप से शामिल हैं।

निहित पैरामीटर

यदि किसी प्रकार के पैरामीटर को एक बार दायरे में परिभाषित किया जाना चाहिए और फिर उस प्रकार के मान का उपयोग करने वाले सभी कार्यों पर लागू किया जाता है, तो निहित पैरामीटर उपयोगी हो सकते हैं।

एक सामान्य फ़ंक्शन कॉल कुछ इस तरह दिखता है:

// import the duration methods
import scala.concurrent.duration._

// a normal method:
def doLongRunningTask(timeout: FiniteDuration): Long = timeout.toMillis

val timeout = 1.second
// timeout: scala.concurrent.duration.FiniteDuration = 1 second

// to call it
doLongRunningTask(timeout) // 1000

अब हम कहते हैं कि हमारे पास कुछ विधियाँ हैं जिनकी सभी समयावधि की अवधि है, और हम उन सभी विधियों को एक ही समय-सीमा का उपयोग करके कॉल करना चाहते हैं। हम टाइमआउट को एक निहित चर के रूप में परिभाषित कर सकते हैं।

// import the duration methods
import scala.concurrent.duration._

// dummy methods that use the implicit parameter
def doLongRunningTaskA()(implicit timeout: FiniteDuration): Long = timeout.toMillis
def doLongRunningTaskB()(implicit timeout: FiniteDuration): Long = timeout.toMillis

// we define the value timeout as implicit
implicit val timeout: FiniteDuration = 1.second

// we can now call the functions without passing the timeout parameter
doLongRunningTaskA() // 1000
doLongRunningTaskB() // 1000

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

ध्यान दें कि यदि आप कार्यक्षेत्र में एक ही प्रकार के दो या दो से अधिक अवक्षेप परिभाषित करते हैं तो यह काम नहीं करेगा।

त्रुटि संदेश को अनुकूलित करने के लिए, टाइप पर implicitNotFound एनोटेशन का उपयोग करें:

@annotation.implicitNotFound(msg = "Select the proper implicit value for type M[${A}]!")
case class M[A](v: A) {}

def usage[O](implicit x: M[O]): O = x.v

//Does not work because no implicit value is present for type `M[Int]`
//usage[Int]   //Select the proper implicit value for type M[Int]!
implicit val first: M[Int] = M(1)
usage[Int]     //Works when `second` is not in scope
implicit val second: M[Int] = M(2)
//Does not work because more than one implicit values are present for the type `M[Int]`
//usage[Int]   //Select the proper implicit value for type M[Int]!

एक टाइमआउट इसके लिए एक सामान्य उपयोग का मामला है, या उदाहरण के लिए अक्का में एक्टरसिस्टम (ज्यादातर बार) हमेशा एक ही होता है, इसलिए यह आमतौर पर अंतर्निहित रूप से पारित हो जाता है। एक अन्य उपयोग का मामला पुस्तकालय का डिजाइन होगा, जो आमतौर पर एफपी पुस्तकालयों के साथ होता है जो कि टाइपकास्ट ( स्कैलेज , बिल्लियों या उत्साह ) पर भरोसा करते हैं।

आम तौर पर इसे इंट , लॉन्ग , स्ट्रिंग आदि जैसे मूल मापदंडों के साथ अंतर्निहित मापदंडों का उपयोग करने के लिए बुरा अभ्यास माना जाता है क्योंकि यह भ्रम पैदा करेगा और कोड को कम पठनीय बना देगा।

इम्प्लिमेंट क्लासेस

अंतर्निहित कक्षाएं पहले से परिभाषित कक्षाओं में नए तरीकों को जोड़ना संभव बनाती हैं।

String क्लास के पास कोई विधि नहीं है बिना withoutVowels । इसे इस तरह जोड़ा जा सकता है:

object StringUtil {
  implicit class StringEnhancer(str: String) {
    def withoutVowels: String = str.replaceAll("[aeiou]", "")
  }
}

अंतर्निहित वर्ग में एक एकल निर्माण पैरामीटर ( str ) उस प्रकार के साथ होता है जिसे आप विस्तारित करना चाहते हैं ( String ) और इसमें वह विधि शामिल होती है जिसे आप टाइप ( withoutVowels ) में "जोड़ना" चाहते हैं। नए परिभाषित तरीकों का उपयोग अब सीधे बढ़ाया प्रकार पर किया जा सकता है (जब बढ़ाया प्रकार अंतर्निहित दायरे में होता है):

import StringUtil.StringEnhancer // Brings StringEnhancer into implicit scope

println("Hello world".withoutVowels) // Hll wrld

हुड के तहत, अंतर्निहित वर्ग इस तरह से अंतर्निहित वर्ग में एक अंतर्निहित रूपांतरण को परिभाषित करते हैं, जैसे:

implicit def toStringEnhancer(str: String): StringEnhancer = new StringEnhancer(str)

रनटाइम ऑब्जेक्ट्स बनाने और इस प्रकार रनटाइम ओवरहेड को हटाने से बचने के लिए अक्सर इंप्लांट क्लास को वैल्यू क्लास के रूप में परिभाषित किया जाता है:

implicit class StringEnhancer(val str: String) extends AnyVal {
    /* conversions code here */
}

उपरोक्त सुधारित परिभाषा के साथ, StringEnhancer का एक नया उदाहरण हर बार withoutVowels विधि के बनाए जाने की आवश्यकता नहीं है।

'निहित' का उपयोग करते हुए समांतर पैरामीटर को हल करना

एक से अधिक अंतर्निहित पैरामीटर के साथ एक अंतर्निहित पैरामीटर सूची को मानते हुए:

case class Example(p1:String, p2:String)(implicit ctx1:SomeCtx1, ctx2:SomeCtx2)

अब, यह मानते हुए कि निहित उदाहरणों में से कोई भी उपलब्ध नहीं है ( SomeCtx1 ), जबकि आवश्यक अन्य सभी अंतर्निहित उदाहरण दायरे में हैं, वर्ग का उदाहरण बनाने के लिए SomeCtx1 का एक उदाहरण प्रदान करना होगा।

यह implicitly कीवर्ड का उपयोग करते हुए एक-दूसरे के इन-स्कोप अंतर्निहित उदाहरण को संरक्षित करते हुए किया जा सकता है:

Example("something","somethingElse")(new SomeCtx1(), implicitly[SomeCtx2])

REPL में नकल

REPL सत्र के दौरान सभी implicits को दायरे में देखने के लिए:

scala> :implicits

Predef.scala में परिभाषित निहित रूपांतरण भी शामिल करने के लिए:

scala> :implicits -v

यदि किसी की अभिव्यक्ति है और उस पर लागू होने वाले सभी पुनर्लेखन नियमों के प्रभाव को देखना चाहता है, तो

scala> reflect.runtime.universe.reify(expr) // No quotes. reify is a macro operating directly on code.

(उदाहरण:

scala> import reflect.runtime.universe._
scala> reify(Array("Alice", "Bob", "Eve").mkString(", "))
resX: Expr[String] = Expr[String](Predef.refArrayOps(Array.apply("Alice", "Bob", "Eve")(Predef.implicitly)).mkString(", "))

)



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow