2012-01-12 12 views
10

निम्नलिखित कोड मार्टिन ओडर्स्की एट अल द्वारा स्कैला पुस्तक में प्रोग्रामिंग से लिया गया है।क्या स्कैला में एक कन्स्ट्रक्टर-स्थानीय चर परिभाषित करना संभव है?

class Rational(n: Int, d: Int) { 
    require(d != 0) 
    private val g = gcd(n.abs, d.abs) 
    val numer = n/g 
    val denom = d/g 
    ... 
    private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) 
} 

यहाँ मूल्य जी केवल जब अंतर्निहित निर्माता initializes क्षेत्रों numer और denom प्रयोग किया जाता है: जो एक तर्कसंगत प्रकार परिभाषित करता है। मान लीजिए प्रोग्रामर जानता है कि यह कहीं और इस्तेमाल नहीं किया जाएगा। उपर्युक्त मामले में यह तर्कसंगत वस्तु के निर्माण के बाद भी सुलभ है। जिसका अर्थ यह है कि यह कन्स्ट्रक्टर को स्थानीय चर होने की बजाए एक निजी क्षेत्र है क्योंकि यह अंतरिक्ष पर भी कब्जा करेगा।

मेरा सवाल यह है कि मैं इस कोड को कैसे बदलूं ताकि g केवल निर्माण के दौरान उपयोग किया जा सके और फिर फेंक दिया जाए?

+2

यह स्कैला में उन "icky अंक" में से एक है। कल्पना कीजिए कि यदि दिए गए कन्स्ट्रक्टर ऑब्जेक्ट का उपयोग केवल कुछ मनमानी जानकारी निकालने के लिए किया जाता था: इसे हमेशा के लिए रखने के लिए इसे पुनः दावा के योग्य होने के बावजूद रखा जाएगा, भले ही जानकारी का केवल एक छोटा सा सबसेट आवश्यक हो। मुझे लगता है कि एक "प्री-क्लास बॉडी" वाक्यविन्यास है, लेकिन मुझे याद नहीं है कि यह क्या है। –

+0

@pst इस त्वरित संपादन के लिए धन्यवाद मैं इस बीच ऐसा कर रहा था। हालांकि आप बेहतर दिखते हैं। :) – ciuncan

+2

यदि किसी के पास इस "प्री-क्लास बॉडी" वाक्यविन्यास के बारे में कोई लिंक है जो पीएसटी का उल्लेख करता है, तो मुझे इसके बारे में सुनना होगा। –

उत्तर

10

इस मामले में, इस तरह के बारे में कैसे?

class Rational(n: Int, d: Int) { 
    require(d != 0) 
    val (numer, denom) = { 
    val g = gcd(n.abs, d.abs) 
    (n/g, d/g) 
    } 
    private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) 
} 

संपादित करें:

public class Rational extends java.lang.Object implements scala.ScalaObject{ 
    private final scala.Tuple2 x$1; // actually unwanted! 
    private final int numer; 
    private final int denom; 
    public int numer(); 
    public int denom(); 
    private int gcd(int, int); 
    public Rational(int, int); 
} 

:
यह भी एक अतिरिक्त क्षेत्र के रूप में संकलित वर्ग (धन्यवाद, एलेक्सी) पर javap चलाकर पता चला है कि, एक टपल रखती है बनाता है

अन्य मामलों में, मैं कभी-कभी locally ब्लॉक का उपयोग करता हूं ताकि प्रत्येकको चालू करने से बचेंएक फ़ील्ड में:

class A { 
    locally { 
    val value1 = // ... 
    val value2 = // ... 
    } 
} 
+0

धन्यवाद, यह संभवतः सबसे अच्छा समाधान हो सकता है। मैंने "स्थानीय रूप से" ब्लॉक के बारे में भी सीखा, इसलिए फिर से धन्यवाद। – ciuncan

+0

क्या मैं उस वर्ग के शरीर में स्थानीय रूप से ब्लॉक में परिभाषित मूल्यों या चर का भी उपयोग कर सकता हूं? या वे स्थानीय रूप से ब्लॉक करने के लिए सिर्फ स्थानीय हैं? – ciuncan

+2

@ciuncan कोड कोड में घोषित कुछ भी (यानी घुंघराले ब्रेसिज़ द्वारा सीमित) उस ब्लॉक के भीतर ही पहुंच योग्य है। 'स्थानीय रूप से' अर्धविराम अनुमान मुद्दों (एक कीवर्ड नहीं) से बचने के लिए सिर्फ एक सुविधाजनक तरीका है, इसलिए इसे बदल नहीं सकता है। 'स्थानीय रूप से 'जानकारी के लिए http://stackoverflow.com/questions/3237727/what-does-predef-locally-do-and-how-is-it- अलग-अलग-predef-identity देखें। –

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