2015-05-25 10 views
8

मैं इस केस क्लास पर टुपल्ड विधि कैसे कॉल कर सकता हूं?स्कैला केस क्लास टुप्लेड

case class(a: Int, b: String)(c: String, d: Int) 

कारण है कि मैं इस तरह मेरे मामले वर्ग है, क्योंकि मैं केवल पहले दो मापदंडों बराबरी और hashCode तुलना के लिए विचार किया जाना उपयोग करना चाहते हैं!

तो मैं इस तरह के केस क्लास पर tupled कैसे ठीक से कॉल कर सकते हैं?

+1

आप इसे एक केस क्लास क्यों चाहते हैं? केस क्लास में कुछ सुविधा विशेषताएं हैं, लेकिन इसके लिए भुगतान लचीलापन का कुछ नुकसान है। बस अपनी खुद की कक्षा को परिभाषित करें और बराबर/हैशकोड को ओवरराइड करें। –

+0

हाँ, मैं समझता हूं लेकिन मैं इस मामले वर्ग पर कुछ भारी पैटर्न मिलान करता हूं, इसलिए मुझे इसे केस क्लास के रूप में छोड़ना है! – sparkr

+1

शायद आप अपने प्रश्न का नाम बदलना चाहते हैं "स्काला केस क्लास एकाधिक पैरामीटर सूची" जैसे टप्लेड –

उत्तर

13

संक्षेप में यह केस क्लास का उपयोग करने के लिए एक अच्छा विचार प्रतीत नहीं होता है। यहां एक स्पष्टीकरण दिया गया है।

के apply और unapply उत्पन्न के साथ एक साथ वर्ग घोषणा जाँच करें:

scala> case class A(a: Int, b: String)(c: String, d: Int) 
defined class A 

scala> A.apply _ 
res0: (Int, String) => (String, Int) => A = <function2> 

scala> A.unapply _ 
res1: A => Option[(Int, String)] = <function1> 

आप देख सकते हैं कि apply कुल (curried), unapply छोड देता है दूसरी सूची में 4 तर्क लेता है, हालांकि।

देखते हैं कि हम दूसरी सूची के सदस्यों तक पहुँच सकते हैं देखते हैं:

scala> val a = A(1, "two")("three", 4) 
a: A = A(1,two) 

scala> a.a 
res2: Int = 1 

scala> a.c 
<console>:11: error: value c is not a member of A 
       a.c 
       ^

... नहीं, नहीं एक नियमित रूप से जिस तरह से। के कुछ और गुण जाँच करें:

scala> a.productArity 
res4: Int = 2 

scala> a.productIterator.toList 
res5: List[Any] = List(1, two) 

ठीक है, यह दूसरा तर्क सूची की तरह लगता है काफी नजरअंदाज कर दिया है। के दशक में खुदाई करते हैं:

scala> :javap A 
... 
    public int a(); 
    descriptor:()I 
    flags: ACC_PUBLIC 
    Code: 
     stack=1, locals=1, args_size=1 
     0: aload_0 
     1: getfield  #16     // Field a:I 
     4: ireturn 
... 
    public java.lang.String b(); 
    descriptor:()Ljava/lang/String; 
    flags: ACC_PUBLIC 
    Code: 
     stack=1, locals=1, args_size=1 
     0: aload_0 
     1: getfield  #21     // Field b:Ljava/lang/String; 
     4: areturn 
... 
    public boolean equals(java.lang.Object); 
    descriptor: (Ljava/lang/Object;)Z 
    flags: ACC_PUBLIC 
    ... //mentions only a and b:.... 
     32: invokevirtual #32     // Method a:()I 
     35: aload   4 
     37: invokevirtual #32     // Method a:()I 
     40: if_icmpne  88 
     43: aload_0 
     44: invokevirtual #35     // Method b:()Ljava/lang/String; 
     47: aload   4 
     49: invokevirtual #35     // Method b:()Ljava/lang/String; 
... 
    public A(int, java.lang.String, java.lang.String, int);                 
    descriptor: (ILjava/lang/String;Ljava/lang/String;I)V                 
    flags: ACC_PUBLIC                          
    Code:                             
     stack=2, locals=5, args_size=5                      
     0: aload_0                          
     1: iload_1                          
     2: putfield  #16     // Field a:I                 
     5: aload_0                          
     6: aload_2                          
     7: putfield  #21     // Field b:Ljava/lang/String;            
     10: aload_0                          
     11: invokespecial #100    // Method java/lang/Object."<init>":()V          
     14: aload_0                          
     15: invokestatic #106    // Method scala/Product$class.$init$:(Lscala/Product;)V      
     18: return                           
     LocalVariableTable:                         
     Start Length Slot Name Signature                    
      0  19  0 this LA;                     
      0  19  1  a I                      
      0  19  2  b Ljava/lang/String;                  
      0  19  3  c Ljava/lang/String;                  
      0  19  4  d I                     

तो वहाँ निर्माता में या इसके बराबर में c और d का कोई उपयोग नहीं है।

आप अब भी उन्हें val साथ लगाकर दूसरे आर्ग सूची उपयोगी पैरामीटर बना सकते हैं:

scala> case class B(a: Int, b: String)(val c: String, val d: Int)   
defined class B               

scala> val b = B(1, "two")("three", 4)          
b: B = B(1,two)               

scala> b.c                 
res6: String = three         

scala> b.d                 
res8: Int = 4  

चलो देखते हैं कैसे समानता और hashCode इस मामले में काम करता है:

scala> val b2 = B(1, "two")("no the same", 555) 
b2: B = B(1,two) 

scala> b == b2 
res10: Boolean = true 

scala> b.hashCode 
res13: Int = -1563217100 

scala> b2.hashCode 
res14: Int = -1563217100 

जिस तरह से आप काम करने के लिए लगता है इसे चाहते हैं, जिसे मैं व्यक्तिगत रूप से पसंद नहीं करता;)

पूर्णता के लिए, डिफ़ॉल्ट पैटर्न मिलान अभी भी A वर्ग के लिए था:

scala> B.unapply _ 
res15: B => Option[(Int, String)] = <function1> 

स्काला भाषा कल्पना बताते हैं कि यह कैसे here काम करता है।

केस श्रेणी के पहले पैरामीटर खंड में औपचारिक पैरामीटर तत्व कहा जाता है; उनका विशेष रूप से इलाज किया जाता है। सबसे पहले, का मान इस तरह के पैरामीटर को कन्स्ट्रक्टर पैटर्न के क्षेत्र के रूप में निकाला जा सकता है। दूसरा, एक वैल उपसर्ग को इस तरह के पैरामीटर में स्पष्ट रूप से जोड़ा जाता है, जब तक पैरामीटर पहले से ही एक वैल या var संशोधक होता है। इसलिए, पैरामीटर के लिए एक्सेसर परिभाषा उत्पन्न होती है।

और

हर मामला वर्ग परोक्ष वर्ग scala.AnyRef करने के कुछ तरीके परिभाषाओं को ओवरराइड करता है जब तक कि एक ही विधि की एक परिभाषा पहले से ही मामला वर्ग खुद या एक ही की एक ठोस परिभाषा दिया जाता है विधि किसी भी श्रेणी से अलग केस वर्ग के कुछ बेस क्लास में दिया गया है। विशेष रूप से:

  • विधि के बराबर होती है: (कोई भी) बूलियन संरचनात्मक समानता, अगर वे दोनों प्रश्न में मामला वर्ग के हैं और वे बराबर है (बराबरी के संबंध में) जहां दो उदाहरणों के बराबर हैं है निर्माता तर्क (कक्षा के तत्वों तक सीमित है, यानी, पहला पैरामीटर अनुभाग)।
  • विधि हैशकोड: Int एक हैश-कोड की गणना करता है। यदि डेटा संरचना सदस्यों के हैशकोड विधियों के बराबर है (बराबर के संबंध में) बराबर हैश-कोड के मान, तो केस क्लास हैशकोड विधि भी करती है।
  • विधि टूस्ट्रिंग: स्ट्रिंग एक स्ट्रिंग प्रतिनिधित्व देता है जिसमें वर्ग और उसके तत्वों का नाम होता है।
+0

बहुत अच्छी तरह से समझाया! – sparkr

+1

बस पूर्णता के लिए (यह देखते हुए कि इस उत्तर में 'tupled' का भी उल्लेख नहीं है), अनुरोध किए गए tupled फ़ंक्शन को पाने का तरीका कुछ ऐसा होगा: 'val tupled = (apapply _)। Tupled.andThen (_.tupled) '। ध्यान दें कि यह पैरामीटर के रूप में ** ** ** ** लेता है (उदाहरण के लिए आप करेंगे: 'tupled ((123, "foo")) (("bar", 456))')। एक फ़ंक्शन में केवल एक सिंगल टुपल लेना (आपके मामले में 'टुपल 4') को टुपल्स को नष्ट किए बिना बॉक्स से बाहर नहीं किया जा सकता है, इसलिए उस बिंदु पर आपको पूरी तरह से मैन्युअल रूप से tupled विधि को लिखना चाहिए। –

+2

असल में: केस क्लास जादू केवल पहली पैरामीटर सूची पर लागू होता है। –

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