2012-11-16 9 views
89

मैं जब तक मैं स्काला संदर्भ में खंड 4.1 देखा था, लगता है कि private val और private final val ही कर रहे हैं प्रयोग किया है:`निजी मूल्य 'और` निजी अंतिम मूल्य' क्यों अलग हैं?

एक निरंतर मूल्य परिभाषा फार्म की है

final val x = e 

(जहां ई एक निरंतर अभिव्यक्ति है §6.24)। अंतिम संशोधक उपस्थित होना चाहिए और कोई भी प्रकार की टिप्पणी नहीं दी जा सकती है। निरंतर मान x के संदर्भ स्वयं को निरंतर अभिव्यक्ति के रूप में माना जाता है; जेनरेट कोड में उन्हें परिभाषा के दाएं हाथ की तरफ से बदल दिया जाता है।

और मैं एक परीक्षण में लिखा है:

class PrivateVal { 
    private val privateVal = 0 
    def testPrivateVal = privateVal 
    private final val privateFinalVal = 1 
    def testPrivateFinalVal = privateFinalVal 
} 

javap -c उत्पादन: private valprivate final val नहीं है:

Compiled from "PrivateVal.scala" 
public class PrivateVal { 
    public int testPrivateVal(); 
    Code: 
     0: aload_0  
     1: invokespecial #19     // Method privateVal:()I 
     4: ireturn  

    public int testPrivateFinalVal(); 
    Code: 
     0: iconst_1  
     1: ireturn  

    public PrivateVal(); 
    Code: 
     0: aload_0  
     1: invokespecial #24     // Method java/lang/Object."<init>":()V 
     4: aload_0  
     5: iconst_0  
     6: putfield  #14     // Field privateVal:I 
     9: return 
} 

बाइट कोड बस के रूप में स्काला संदर्भ कहा है।

क्यों नहीं scalac सिर्फ private valprivate final val के रूप में इलाज करता है? क्या कोई अंतर्निहित कारण है?

+24

दूसरे शब्दों में: चूंकि 'वैल' पहले से ही अपरिवर्तनीय है, इसलिए हमें स्केल में 'अंतिम' कीवर्ड क्यों चाहिए? कंपाइलर 'वैल' के समान वैल्यू का इलाज क्यों नहीं कर सकता? – Jesper

+0

ध्यान दें कि 'निजी' स्कोप संशोधक के पास जावा में 'पैकेज निजी' के समान अर्थशास्त्र है। आप 'निजी [यह]' कह सकते हैं। –

+3

@ConnorDoyle: पैकेज निजी के रूप में? मुझे ऐसा नहीं लगता: 'निजी' का मतलब है कि यह केवल इस वर्ग के उदाहरणों के लिए दृश्यमान है, 'निजी [यह]' केवल इस उदाहरण - एक ही ** कक्षा ** के उदाहरणों को छोड़कर, 'निजी' अनुमति नहीं देता है मूल्य तक पहुंचने के लिए कोई भी (उसी पैकेज से शामिल)। – Make42

उत्तर

75

तो, यह सिर्फ एक अनुमान है, लेकिन यह जावा में बारहमासी परेशानी थी कि दाईं ओर एक शाब्दिक के साथ अंतिम स्थैतिक चर को बाइटकोड में स्थिरांक के रूप में रेखांकित किया जाता है। यह एक प्रदर्शन लाभ सुनिश्चित करता है, लेकिन यह "निरंतर" कभी भी परिवर्तित होने पर परिभाषा की बाइनरी संगतता का कारण बनता है। एक अंतिम स्थैतिक चर को परिभाषित करते समय जिनके मूल्य को बदलने की आवश्यकता हो सकती है, जावा प्रोग्रामर को किसी विधि या कन्स्ट्रक्टर के साथ मूल्य प्रारंभ करने जैसे हैक्स का सहारा लेना पड़ता है।

स्कैला में एक वैल जावा अर्थ में पहले से ही अंतिम है। ऐसा लगता है जैसे स्कैला के डिजाइनर अनावश्यक संशोधक फाइनल का उपयोग "निरंतर मूल्य को रेखांकित करने की अनुमति" के लिए कर रहे हैं। इसलिए स्कैला प्रोग्रामर के पास इस व्यवहार पर हैक का उपयोग किए बिना इस व्यवहार पर पूर्ण नियंत्रण है: यदि वे एक अनिर्धारित निरंतर चाहते हैं, तो एक मूल्य जो कभी नहीं बदला जाना चाहिए लेकिन तेज़ है, वे "अंतिम वैल" लिखते हैं। यदि वे बाइनरी संगतता को तोड़ने के बिना मूल्य को बदलने के लिए लचीलापन चाहते हैं, तो बस "वैल"।

+8

हां, यह गैर-निजी vals के कारण है, लेकिन निजी vals स्पष्ट रूप से अन्य वर्गों में रेखांकित नहीं किया जा सकता है और उसी तरह संगतता तोड़ सकता है। –

+3

क्या मैं 'निजी मूल्य' को 'निजी अंतिम मूल्य' में बदलता हूं, तो क्या कोई बाइनरी संगतता समस्या है? –

+1

@ स्टीव-वाल्डमैन क्षमा करें, क्या आपका मतलब आपके दूसरे पैराग्राफ में 'वैल' था? –

7

मुझे लगता है कि यहां भ्रम अंतिम के अर्थशास्त्र के साथ अपरिवर्तनीयता को दूर करने से उत्पन्न होता है। val एस को बाल कक्षाओं में ओवरराइड किया जा सकता है और इसलिए इसे स्पष्ट रूप से तब तक नहीं माना जा सकता जब तक कि स्पष्ट रूप से चिह्नित न किया जाए।

@ ब्रायन आरईपीएल लाइन स्तर पर कक्षा का दायरा प्रदान करता है। देखें:

scala> $iw.getClass.getPackage 
res0: Package = package $line3 

scala> private val x = 5 
<console>:5: error: value x cannot be accessed in object $iw 
    lazy val $result = `x` 

scala> private val x = 5; println(x); 
5 
+1

मैं बात कर रहा हूं 'निजी मूल्य 'के बारे में। क्या यह अतिरंजित हो सकता है? –

+0

नहीं, निजी vals overriden नहीं किया जा सकता है। आप उप-वर्ग में एक ही नाम के साथ एक और निजी वैल को फिर से परिभाषित कर सकते हैं, लेकिन यह एक बिल्कुल अलग वैल है जो कि वही नाम होता है। (पुराने व्यक्ति के सभी संदर्भ अभी भी पुराने को संदर्भित करेंगे।) – aij

+1

हालांकि यह केवल ओवरराइडिंग व्यवहार प्रतीत नहीं होता है, क्योंकि मैं बिना किसी त्रुटि के दुभाषिया पर अंतिम वैल (या यहां तक ​​कि अंतिम var) भी बना सकता हूं एक वर्ग का संदर्भ बिल्कुल। – Brian

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