स्काला मल्टीपल टाइप पैटर्न मैचिंग


80

मैं सोच रहा हूं कि मैं कई प्रकार के पैटर्न मिलान का उपयोग कैसे कर सकता हूं। मेरे पास है:

abstract class MyAbstract

case class MyFirst extends MyAbstract
case class MySecond extends MyAbstract
case class MyThird extends MyAbstract // shouldn't be matched and shouldn't call doSomething()

val x: MyAbstract = MyFirst

x match { 
 case a: MyFirst => doSomething()
 case b: MySecond => doSomething()
 case _ => doSomethingElse()
}

इसलिए मैं कुछ लिखना चाहूंगा:

x match {
 case a @ (MyFirst | MySecond) => doSomething()
 case _ => doSomethingElse()
}

मैंने कुछ ट्यूटोरियल में समान निर्माण देखा, लेकिन यह मुझे त्रुटि देता है:

pattern type is incompatible with expected type;
[error]  found   : object MyFirst
[error]  required: MyAbstract

तो क्या मामले के खंड में कुछ अलग-अलग प्रकारों को परिभाषित करने का एक तरीका है? मुझे लगता है कि यह कोड को सुंदर बना देगा। जैसे कि मेरे पास उनमें से 5 होंगे, मैं एक ही कोड को 5 बार (doSomething () कॉलिंग) लिखूंगा।

अग्रिम में धन्यवाद!


मुझे लगता है कि यह एक XY- समस्या है; आपके पास सभी doSomethingमामलों के लिए एक सामान्य सुपरक्लास है , case a : MyAbstractतो तत्कालीन मेल क्यों नहीं ...?
— पैट्रिक iewiek

क्षमा करें, यह उल्लेख करना भूल गया कि मेरे पास अन्य कक्षाएं हैं, जो MyAbstract वर्ग का विस्तार करती हैं और doSomething को कॉल नहीं करना चाहिए।
— Psisoyev

ओह, ठीक है, बस यह स्पष्ट करना चाहता था कि :) आपके पास अब आपकी समस्या का एक सही उत्तर है।
— पेट्रीक kwiek

जवाबों:


135

आप अपनी केस कक्षाओं के लिए कोष्ठक को याद कर रहे हैं। पैरामीटर सूचियों के बिना केस की कक्षाओं को पदावनत किया जाता है।

इसे इस्तेमाल करे:

abstract class MyAbstract
case class MyFirst() extends MyAbstract
case class MySecond() extends MyAbstract

val x: MyAbstract = MyFirst()


x match {
   case aOrB @ (MyFirst() | MySecond()) => doSomething(aOrB)
   case _ => doSomethingElse()
}

यदि आपके पास अपने केस क्लासेस के लिए बहुत सारे परमेस हैं और लंबे Foo(_,_,..)पैटर्न लिखना पसंद नहीं करते हैं , तो हो सकता है:

x match {
   case aOrB @ (_:MyFirst | _:MySecond) => doSomething(aOrB)
   case _ => doSomethingElse()
}

या केवल:

x match {
   case _:MyFirst | _:MySecond => doSomething(x) // just use x instead of aOrB
   case _ => doSomethingElse(x)
}

लेकिन शायद आप सिर्फ सिंगलटन केस ऑब्जेक्ट्स चाहते थे?

abstract class MyAbstract
case object MyFirst extends MyAbstract
case object MySecond extends MyAbstract

val x: MyAbstract = MyFirst

x match {
   case aOrB @ (MyFirst | MySecond) => doSomething()
   case _ => doSomethingElse()
}

1
और कोष्ठक से बचने का कोई उपाय नहीं है? जैसा कि मेरे पास कुछ पैरामीटर हैं और यह बदसूरत हो जाता है: मामला a @ (MyFirst ( , _, _, _, _) | MySecond ( , _, _, _, _)) => doSomething ()
— psisemev

9
क्या आपको याद आया obj @ (_: MyFirst | _: MySecond)?
— जीन-फिलिप पेलेट

मुझे objऐसे मामलों की आवश्यकता है, जहां मैं इसे doSomethingकॉल में उपयोग कर रहा हूं । मेरे मामले में, कॉल का doSomethingउपयोग नहीं किया गया था obj, इसलिए मुझे इसकी आवश्यकता नहीं है। लेकिन वैसे भी, आपकी टिप्पणी के लिए धन्यवाद!
— Psisoyev

@ जीन-फिलिप्पेलेट वास्तव में मेरे पास है। मुझे इसे जोड़ने के लिए अपनी पोस्ट को संपादित करने दें।
— फैज

1
यह अच्छा होगा यदि संकलित इनपुट प्रकार को डिफ़ॉल्ट करने के बजाय निकटतम सामान्य प्रकार खोजने के लिए पर्याप्त स्मार्ट था।
— nilskp
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.