2013-02-18 13 views
43

मैं एक विस्तार विधिक्या निहित वर्ग हमेशा किसी भीवल का विस्तार करना चाहिए?

implicit class EnhancedFoo(foo: Foo) { 
    def bar() { /* ... */ } 
} 

आप हमेशा वर्ग defininition में extends AnyVal शामिल करना चाहिए लिख रहा हूँ कहो? आप किस परिस्थिति में एक अंतर्निहित वर्ग को मूल्य वर्ग नहीं बनाना चाहते हैं?

उत्तर

38

के limitations listed for value classes को देखो और लगता है कि जब वे निहित कक्षाओं के लिए उपयुक्त नहीं हो सकता है:

  1. "ठीक एक सार्वजनिक, वैल पैरामीटर जिसका प्रकार एक मूल्य वर्ग नहीं है साथ ही एक प्राथमिक निर्माता होना आवश्यक है। " तो अगर आप वर्ग लपेटकर कर रहे हैं अपने आप में एक मूल्य वर्ग है, तो आप एक आवरण के रूप में एक implicit class उपयोग नहीं कर सकते, लेकिन आप यह कर सकते हैं: अपने आवरण अंतर्निहित पैरामीटर के रूप में अच्छी तरह से है

    // wrapped class 
    class Meters(val value: Int) extends AnyVal { ... } 
    
    // wrapper 
    class RichMeters(val value: Int) extends AnyVal { ... } 
    
    object RichMeters { 
        implicit def wrap(m: Meter) = new RichMeter(m.value) 
    } 
    

    हैं, तो आप की कोशिश कर सकते उन्हें विधि घोषणाओं में ले जाएं। अर्थात।

    implicit class RichFoo[T](foo: Foo[T])(implicit ord: Ordering[T]) { 
        def bar(otherFoo: Foo[T]) = // something using ord 
    } 
    

    के बजाय आप

    implicit class RichFoo[T](foo: Foo[T]) extends AnyVal { 
        def bar(otherFoo: Foo[T])(implicit ord: Ordering[T]) = // something using ord 
    } 
    
  2. "विशेष प्रकार पैरामीटर नहीं हो सकता है।" है आप एक वर्ग को लपेटते समय रैपर को विशेषीकृत करना चाहते हैं, जिसमें स्वयं विशेष प्रकार के पैरामीटर हैं।

  3. "नेस्टेड या स्थानीय वर्ग, लक्षण या वस्तुएं नहीं हो सकती हैं" फिर, कुछ ऐसा जो एक रैपर को लागू करने के लिए उपयोगी हो सकता है।
  4. "equals या hashCode विधि को परिभाषित नहीं कर सकता है।" अप्रासंगिक, क्योंकि निहित कक्षाओं में equals/hashCode नहीं होना चाहिए।
  5. "एक शीर्ष-स्तरीय कक्षा या स्थिर रूप से सुलभ वस्तु का सदस्य होना चाहिए" यह वह जगह भी है जहां आप सामान्य रूप से अंतर्निहित कक्षाओं को परिभाषित करेंगे, लेकिन आवश्यक नहीं है।
  6. "केवल सदस्यों के रूप में defs हो सकता है। विशेष रूप से, यह आलसी vals, vars, या vals सदस्यों के रूप में नहीं हो सकता है।" लागू वर्गों में वे सभी हो सकते हैं, हालांकि मैं var एस या lazy val एस के लिए एक समझदार उपयोगकेस के बारे में नहीं सोच सकता।
  7. "किसी अन्य वर्ग द्वारा विस्तारित नहीं किया जा सकता है।" फिर, निहित वर्गों को बढ़ाया जा सकता है, लेकिन शायद कोई अच्छा कारण नहीं है।

इसके अलावा, अपनी अंतर्निहित कक्षा बनाने के लिए मूल्य वर्ग संभवतः प्रतिबिंब का उपयोग करके कोड के कुछ व्यवहार को बदल सकता है, लेकिन प्रतिबिंब सामान्य रूप से निहित कक्षाओं को नहीं देखना चाहिए।

यदि आपकी निहित कक्षा उन सभी सीमाओं को पूरा करती है, तो मैं इसे एक मूल्य वर्ग नहीं बनाने के कारण के बारे में नहीं सोच सकता।

+0

fwiw, यहां 'आलसी वर्ग' के अंदर 'आलसी वाल' के लिए उपयोग का मामला है: https: //gist.github।कॉम/सेथटिस्यू/8977033। सौभाग्य से एक आसान कामकाज है (जिस्ट में भी दिखाया गया है)। –

+1

"मैं इस कारण के बारे में सोच नहीं सकता कि इसे मूल्य वर्ग नहीं बनाया जाए।" - क्योंकि यह विचलित है लेकिन कोई लाभ नहीं देता है। मैं अपने परीक्षणों में "AnyVal" अंतर्निहित कक्षाओं के अनुमानित स्मृति लाभों को पुन: उत्पन्न करने में सक्षम नहीं हूं। क्या आपके पास लाभ के लिए उद्धरण है? – Rich

+0

प्रलेखन अभी भी इसकी अनुशंसा करता है, लेकिन मैं अपने परीक्षणों में किसी भी लाभ को माप नहीं सकता। http://docs.scala-lang.org/overviews/core/value-classes.html – Rich

2

मुझे लगता है कि आप Value Classes को Implicit Classes के साथ भ्रमित कर रहे हैं। एक वृद्धि के लिए एक लागू वर्ग को परिभाषित करते समय आप शायद ही कभी कुछ भी बढ़ाएंगे जबकि वैल्यू क्लासेस AnyVal का विस्तार करना होगा।

+11

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

+2

मूल्य वर्गों में बहुत से प्रतिबंध हैं। यदि वे उपयुक्त हैं, तो निश्चित रूप से, उन्हें एक वृद्धि के लिए उपयोग करें। –

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