2012-05-18 21 views
15

मुझे पता है कि आपको केस कक्षाओं से उत्तराधिकारी होने की अनुमति नहीं है, लेकिन जब आपको वास्तव में आवश्यकता होती है तो आप कैसे करेंगे? हमारे पास पदानुक्रम में दो वर्ग हैं, दोनों में कई फ़ील्ड हैं, और हमें दोनों के उदाहरण बनाने में सक्षम होना चाहिए। hashCode तरीकों आदि पदानुक्रम की आवश्यकता होने पर केस कक्षाओं का उपयोग कैसे करें?

  • अगर मैं इस तरह के toString के रूप में सभी मामले वर्ग अच्छाई खो देंगे, के बराबर होती है, -

    • मैं सुपर वर्ग एक मामला वर्ग के बजाय एक सामान्य वर्ग बनाने चाहते हैं: यहाँ मेरी विकल्प है मैं इसे एक केस क्लास के रूप में रखता हूं, मैं केस कक्षाओं से विरासत में नहीं होने का नियम तोड़ दूंगा।
    • यदि मैं बाल वर्ग में संरचना का उपयोग करता हूं - मुझे कई तरीकों को लिखना होगा और उन्हें अन्य वर्ग में रीडायरेक्ट करना होगा - जिसका मतलब बहुत सारे काम होगा और गैर-स्कालिश महसूस होगा।

    मुझे क्या करना चाहिए? क्या यह काफी आम समस्या नहीं है?

  • उत्तर

    9

    हाँ यह है काफी आवर्ती समस्या, wha टी मैं सुझाव दूंगा कि सभी मूल गुणों के साथ एक विशेषता बनाने के लिए, एक केस क्लास बनाएं जो इसे लागू करता है और फिर दूसरा गुण जो अधिक गुणों के साथ प्राप्त करता है।

    sealed trait Parent { 
        /* implement all common properties */ 
    } 
    
    case class A extends Parent 
    
    case class B extends Parent { 
        /*add all stuff you want*/ 
    } 
    

    इसे देखने का एक अच्छा तरीका एक पेड़ है, लक्षण नोड्स हैं और केस कक्षाएं पत्तियां हैं।

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

    संपादित करें: टिप्पणियों में सुझाव के अनुसार, यदि आप सभी केस कक्षाओं को पैटर्न मिलान में शामिल नहीं करते हैं तो संकलन में अपवाद रखने के लिए आप विशेषता को सील कर सकते हैं। उदाहरण के लिए यह "प्रोग्रामिंग इन स्कैला" के अध्याय 15.5 में वर्णित है

    +6

    विशेषता सील भी एक अच्छा विचार होगा। – agilesteel

    3

    मैं भी इस मुद्दे का पता लगाया, AFAIK, सबसे अच्छा आप प्राप्त करने के लिए जा रहे हैं है:

    प्रत्येक मामले वर्ग एक आम विशेषता परिभाषित करता है कि सार गुण प्रत्येक मामले वर्ग

    को लागू करना चाहिए से विस्तार है

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

    6

    प्रतिनिधिमंडल के साथ विरासत को बदलने के बारे में क्या?

    यदि पदानुक्रम में आपके दो वर्गों में साझा फ़ील्ड साझा किए गए हैं, तो प्रतिनिधिमंडल बॉयलरप्लेट कोड की मात्रा को कम कर सकता है? इसलिए जैसा:

    case class Something(aa: A, bb: B, cc: C, payload: Payload) 
    
    sealed abstract class Payload 
    
    case class PayloadX(xx: X) extends Payload 
    case class PayloadY(yy: Y) extends Payload 
    

    और फिर आप तो जैसे Something उदाहरण बना होगा:

    val sth1 = Something('aa', 'bb', 'cc', PayloadX('xx')) 
    val sth2 = Something('aa', 'bb', 'cc', PayloadY('yy')) 
    

    और तुम पैटर्न मिलान कर सकता है:

    sth1 match { 
        case Something(_, _, _, PayloadX(_)) => ... 
        case Something(_, _, _, PayloadY(_)) => ... 
    } 
    

    लाभ: (?)

    • जब आप घोषित PayloadX और PayloadY, आप कुछ में सभी क्षेत्रों को दोहराने की जरूरत नहीं है।

    • जब आप Something(... Payload(..)) का उदाहरण बना है, तो आप कोड है कि Something बनाता पुन: उपयोग कर सकते हैं, दोनों जब आप एक Something(... PayloadX(..)) और ...PayloadY पैदा करते हैं।

    कमियां: (?)

    • शायद PayloadX और Y अपने मामले में वास्तव में अपने मामले में Something का सच उपवर्गों कर रहे हैं, मेरा मतलब है, शायद प्रतिनिधिमंडल शब्दार्थ गलत क्या है?

    • आप बस something.whatever के बजाय something.payload.whatever लिखने के लिए होता है (मैं इस अपने विशेष मामले के आधार पर अच्छा या बुरा हो सकता है लगता है?)

    +0

    एक और दोष: आप अब विधि हस्ताक्षर में विशिष्ट प्रकारों के बारे में बात करने में सक्षम नहीं होंगे, यह हमेशा "कुछ" होगा। – Vituel