संक्षेप में यह केस क्लास का उपयोग करने के लिए एक अच्छा विचार प्रतीत नहीं होता है। यहां एक स्पष्टीकरण दिया गया है।
के 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 एक हैश-कोड की गणना करता है। यदि डेटा संरचना सदस्यों के हैशकोड विधियों के बराबर है (बराबर के संबंध में) बराबर हैश-कोड के मान, तो केस क्लास हैशकोड विधि भी करती है।
- विधि टूस्ट्रिंग: स्ट्रिंग एक स्ट्रिंग प्रतिनिधित्व देता है जिसमें वर्ग और उसके तत्वों का नाम होता है।
आप इसे एक केस क्लास क्यों चाहते हैं? केस क्लास में कुछ सुविधा विशेषताएं हैं, लेकिन इसके लिए भुगतान लचीलापन का कुछ नुकसान है। बस अपनी खुद की कक्षा को परिभाषित करें और बराबर/हैशकोड को ओवरराइड करें। –
हाँ, मैं समझता हूं लेकिन मैं इस मामले वर्ग पर कुछ भारी पैटर्न मिलान करता हूं, इसलिए मुझे इसे केस क्लास के रूप में छोड़ना है! – sparkr
शायद आप अपने प्रश्न का नाम बदलना चाहते हैं "स्काला केस क्लास एकाधिक पैरामीटर सूची" जैसे टप्लेड –