2010-05-18 13 views
7

और अधिक विशेष रूप से BigInt int को BigInt में परिवर्तित करने के लिए कैसे काम करता है?क्या कोई मुझे स्कैला में अंतर्निहित रूपांतरण समझा सकता है?

स्रोत कोड इसे पढ़ता में:

... 
implicit def int2bigInt(i: Int): BigInt = apply(i) 
... 

इस कोड को लागू कैसे किया जाता है?

मैं समझ सकता हूं कि यह अन्य नमूना कैसे: "Date literals" काम करता है।

इन।

val christmas = 24 Dec 2010 

द्वारा निर्धारित:

implicit def dateLiterals(date: Int) = new { 
    import java.util.Date 
    def Dec(year: Int) = new Date(year, 11, date) 
} 

int मिलता है पैरामीटर के रूप में एक int साथ संदेश Dec पारित कर दिया है, सिस्टम एक और तरीका है कि अनुरोध संभाल कर सकते हैं के लिए लग रहा है, इस मामले में Dec(year:Int)

Q1। क्या मैं तारीख साहित्य की मेरी समझ में सही हूं?

प्रश्न 2। यह BigInt पर कैसे लागू होता है?

धन्यवाद

+0

मुझे लगता है कि आप निहित रूपांतरणों का जिक्र कर रहे हैं। लागू पैरामीटर थोड़ा अलग बात है। – GClaramunt

+0

[स्कैला प्रथम संस्करण में प्रोग्रामिंग] (http://www.artima.com/pins1ed/): [लागू रूपांतरण और पैरामीटर] (http://www.artima.com/pins1ed/implicit-conversions-and-parameters। एचटीएमएल) – user272735

उत्तर

11

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

doSomethingWithBigInt(d:BigInt)=.... 

हैं और आप एक पूर्णांक से कॉल करने की:

doSomethingWithBigInt(10) 

प्रकार से मेल नहीं खाते के रूप में, स्काला संकलक उत्पन्न करेगा:

doSomethingWithBigInt(int2bigInt(10)) 

निहित int2bigInt मानते हुए दायरे में

+2

स्पष्टीकरण के लिए, यह एक अंतर्निहित * का उपयोग करता है यदि यह कोड बनायेगा जो अन्यथा संकलित नहीं करेगा *, न केवल अगर कोई अंतर्निहित है जो पाया गया प्रकार को इसके तर्क के रूप में स्वीकार करता है। –

+3

दायरा चीज एक लाल हेरिंग है। स्कैला मूल वर्ग के सहयोगी वस्तु में और गंतव्य वर्ग के सहयोगी वस्तु में ऐसे निहितार्थों की खोज करेगा यदि उस गंतव्य वर्ग का अनुमान लगाया गया है। इस मामले में, चूंकि गंतव्य वर्ग स्पष्ट रूप से BigInt है, तो BigInt के ऑब्जेक्ट साथी को implicits के लिए खोजा जाएगा। –

+0

मैं दायरे के बारे में विवरण में नहीं जाना चाहता था :) – GClaramunt

7

निहित रों की बात है टफ को उबाऊ बॉयलरप्लेट सामान भरना है जब इसे करने के लिए स्पष्ट रूप से केवल एक सही तरीका है।

के मामले में अंतर्निहित पैरामीटर संकलक संदर्भ से एक पैरामीटर डालता है जो आप सोच रहे थे। उदाहरण के लिए,

case class TaxRate(rate: BigDecimal) { } 
implicit var sales_tax = TaxRate(0.075) 
def withTax(price: BigDecimal)(implicit tax: TaxRate) = price*(tax.rate+1) 

scala> withTax(15.00) 
res0: scala.math.BigDecimal = 16.1250 

हम एक अंतर्निहित पैरामीटर के रूप में कर की दर में चिह्नित किया है, और एक अंतर्निहित चर जब जरूरत में भरा जा सकता है कि प्रदान की जाती बाद से, हम कर की दर को निर्दिष्ट करने की जरूरत नहीं है। संकलक स्वचालित रूप से withTax(15.00)(sales_tax)

में भर जाता है अंतर्निहित रूपांतरण के मामले में, संकलक एक विधि है कि एक प्रकार यह है कि लेने के लिए और यह प्रकार है कि जरूरत है करने के लिए परिवर्तित कर सकते हैं के लिए लग रहा है। इस रूपांतरण को सामान्य परिस्थितियों में जंजीर नहीं बनाया जा सकता है, इसलिए आपको एक चरण में जो चाहिए उसे प्राप्त करना होगा।

ऐसे दो मामले हैं जहां निहित रूपांतरण खेलने की संभावना है। एक विधि कॉल के पैरामीटर में है - यदि प्रकार गलत है, लेकिन इसे सही प्रकार (बिल्कुल एक तरफ) में परिवर्तित किया जा सकता है, तो संकलक आपके लिए परिवर्तित हो जाएगा। दूसरा एक विधि कॉल के उपस्थिति में है - यदि वास्तव में उपयोग किए जाने वाले प्रकार में विधि उपलब्ध नहीं है, लेकिन आप इसे उस प्रकार में परिवर्तित कर सकते हैं जिसमें वह विधि है, तो रूपांतरण होगा और फिर विधि बुलाया जाएगा।

चलो प्रत्येक का एक उदाहरण देखें।

implicit def float2taxrate(f: Float) = TaxRate(BigDecimal(f)) 
scala> withTax(15.00)(0.15f) 
res1: scala.math.BigDecimal = 17.250000089406967200 

यहाँ, हम 0.15f की एक स्पष्ट कर की दर कहते हैं। यह पैरामीटर से मेल नहीं खाता है, जो TaxRate टाइप होना चाहिए, लेकिन संकलक देखता है कि हम अंतर्निहित float2taxrate का उपयोग कर कर दरों में फ्लोट कर सकते हैं। तो यह हमारे लिए करता है, withTax(15.00)(float2taxrate(0.15f))

अब अन्य उदाहरण। (के रूप में यह एक BigDecimal रिटर्न)

class Currency(bd: BigDecimal) { 
    def rounded = bd.setScale(2,BigDecimal.RoundingMode.HALF_EVEN) 
} 
implicit def bigdec2currency(bd: BigDecimal) = new Currency(bd) 
scala> withTax(15.00)(0.15f).rounded 
res66: scala.math.BigDecimal = 17.25 

BigDecimal एक rounded विधि नहीं है, तो withTax(15.00)(0.15f) एक कॉल करने के लिए सक्षम नहीं होना चाहिए। लेकिन हमने Currency परिभाषित किया है जिसमें rounded विधि है, और Currency में रूपांतरण है, इसलिए अंतर्निहित रूपांतरण सभी विवरणों में भर जाता है: bigdec2currency(withTax(15.00)(0.15f)).rounded

Int से BigInt में रूपांतरण के मामले में, संकलक इसका उपयोग करेगा, उदाहरण के लिए, यह 7 + BigInt(5) जोड़ने का प्रयास करता है। यह सामान्य रूप से काम नहीं करेगा - 7 एक Int और Int नहीं जानता है कि BigInt पर खुद को कैसे जोड़ना है। लेकिन BigInt में एक विधि + है जो स्वयं को BigInt पर जोड़ सकती है। और संकलक देखता है कि अगर यह केवल 7 को BigInt में परिवर्तित कर सकता है, तो वह उस विधि का उपयोग कर सकता है। अंतर्निहित रूपांतरण उस रूपांतरण की अनुमति देता है, इसलिए यह 7 + BigInt(5) का अनुवाद int2bigInt(7)+BigInt(5) में करता है।

(नोट:। int2bigInt तो यह उपयोग करने के लिए आप import BigInt._ करने के लिए है और यह बदले में BigInt वस्तु की apply(i: Int) विधि है, जो कि तुम क्या BigInt(5) लिख सकते हैं और यह काम (बजाय देता है को defers BigInt अंदर परिभाषित किया गया है, जावा में BigInteger के साथ एक स्ट्रिंग पास करने के लिए)।

+0

धन्यवाद! यह मेरी व्याख्या से अधिक विस्तृत है। – GClaramunt

+0

आपकी संभावना पर्याप्त थी, लेकिन मैंने उन लोगों के लिए एक लंबा संदर्भ/ट्यूटोरियल छोड़ने का फैसला किया जो स्कैला से कम परिचित हैं। –

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