खोज…


टिप्पणियों

sealed trait और case objects साथ दृष्टिकोण को प्राथमिकता दी जाती है क्योंकि स्काला एन्यूमरेशन में कुछ समस्याएं हैं:

  1. उन्मूलन के बाद एनुमरेशन्स का एक ही प्रकार है।
  2. कंपाइलर को "माचिस थकावट नहीं है" के बारे में शिकायत नहीं है, अगर मामला छूट जाता है तो यह रनटाइम scala.MatchError में विफल हो जाएगा।
def isWeekendWithBug(day: WeekDays.Value): Boolean = day match {
  case WeekDays.Sun | WeekDays.Sat => true
}

isWeekendWithBug(WeekDays.Fri)
scala.MatchError: Fri (of class scala.Enumeration$Val)

तुलना करना:

def isWeekendWithBug(day: WeekDay): Boolean = day match {
  case WeekDay.Sun | WeekDay.Sat => true
}

Warning: match may not be exhaustive.
It would fail on the following inputs: Fri, Mon, Thu, Tue, Wed
def isWeekendWithBug(day: WeekDay): Boolean = day match {
                                          ^

इस लेख में स्काला एन्यूमरेशन के बारे में अधिक विस्तृत विवरण प्रस्तुत किया गया है।

सप्ताह का दिन स्काला एन्यूमरेशन का उपयोग करते हुए

Enumeration को बढ़ाकर Java जैसे Enumerations बनाए जा सकते हैं।

object WeekDays extends Enumeration {
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}

def isWeekend(day: WeekDays.Value): Boolean = day match {
  case WeekDays.Sat | WeekDays.Sun => true
  case _ => false
}

isWeekend(WeekDays.Sun)
res0: Boolean = true

किसी गणना में मानों के लिए मानव-पठनीय नाम जोड़ना भी संभव है:

object WeekDays extends Enumeration {
      val Mon = Value("Monday")
      val Tue = Value("Tuesday")
      val Wed = Value("Wednesday")
      val Thu = Value("Thursday")
      val Fri = Value("Friday")
      val Sat = Value("Saturday")
      val Sun = Value("Sunday")
}

println(WeekDays.Mon)
>> Monday

WeekDays.withName("Monday") == WeekDays.Mon
>> res0: Boolean = true

विभिन्न प्रकार के व्यवहारों से सावधान रहें, जिसमें विभिन्न गणनाएं एक ही उदाहरण प्रकार के रूप में मूल्यांकन कर सकती हैं:

object Parity extends Enumeration {
   val Even, Odd = Value
}
  
WeekDays.Mon.isInstanceOf[Parity.Value]
>> res1: Boolean = true

मुहरबंद विशेषता और केस ऑब्जेक्ट का उपयोग करना

विस्तारित Enumeration का एक विकल्प sealed केस ऑब्जेक्ट्स का उपयोग sealed है:

sealed trait WeekDay

object WeekDay {
  case object Mon extends WeekDay
  case object Tue extends WeekDay
  case object Wed extends WeekDay
  case object Thu extends WeekDay
  case object Fri extends WeekDay
  case object Sun extends WeekDay
  case object Sat extends WeekDay
}

sealed कीवर्ड गारंटी देता है कि विशेषता WeekDay को दूसरी फाइल में नहीं बढ़ाया जा सकता है। यह संकलक को कुछ मान्यताओं को बनाने की अनुमति देता है, जिसमें यह भी शामिल है कि WeekDay सभी संभावित मूल्य पहले से ही एन्यूमरेटेड हैं।

एक दोष यह है कि यह विधि आपको सभी संभावित मूल्यों की सूची प्राप्त करने की अनुमति नहीं देती है। ऐसी सूची प्राप्त करने के लिए इसे स्पष्ट रूप से प्रदान किया जाना चाहिए:

val allWeekDays = Seq(Mon, Tue, Wed, Thu, Fri, Sun, Sat)

केस क्लासेस एक sealed विशेषता का विस्तार भी कर सकते हैं। इस प्रकार, जटिल पदानुक्रम बनाने के लिए वस्तुओं और केस वर्गों को मिलाया जा सकता है:

sealed trait CelestialBody
    
object CelestialBody {
  case object Earth extends CelestialBody
  case object Sun extends CelestialBody
  case object Moon extends CelestialBody
  case class Asteroid(name: String) extends CelestialBody
}

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

  sealed trait WeekDay { val name: String }

  object WeekDay {
      case object Mon extends WeekDay { val name = "Monday" }
      case object Tue extends WeekDay { val name = "Tuesday" }
      (...)   
  }

या केवल:

  sealed case class WeekDay(name: String)
    
  object WeekDay {
      object Mon extends WeekDay("Monday")
      object Tue extends WeekDay("Tuesday")
      (...)   
  }

सीलबंद विशेषता और केस ऑब्जेक्ट और ऑलवैल्यू-मैक्रो का उपयोग करना

यह सीलबंद विशेषता संस्करण पर एक विस्तार है जहां एक मैक्रो संकलन समय पर सभी उदाहरणों के साथ एक सेट उत्पन्न करता है। यह अच्छी तरह से खामी को छोड़ देता है कि एक डेवलपर एन्यूमरेशन के लिए एक मूल्य जोड़ सकता है लेकिन इसे ऑलआउट सेट में जोड़ना भूल सकता है।

यह वैरिएंट खासतौर पर बड़े एनम के लिए उपयोगी है।

import EnumerationMacros._

sealed trait WeekDay
object WeekDay {
  case object Mon extends WeekDay
  case object Tue extends WeekDay
  case object Wed extends WeekDay
  case object Thu extends WeekDay
  case object Fri extends WeekDay
  case object Sun extends WeekDay
  case object Sat extends WeekDay
  val allWeekDays: Set[WeekDay] = sealedInstancesOf[WeekDay]
}

इस कार्य के लिए आपको इस मैक्रो की आवश्यकता है:

import scala.collection.immutable.TreeSet
import scala.language.experimental.macros
import scala.reflect.macros.blackbox

/**
A macro to produce a TreeSet of all instances of a sealed trait.
Based on Travis Brown's work:
http://stackoverflow.com/questions/13671734/iteration-over-a-sealed-trait-in-scala
CAREFUL: !!! MUST be used at END OF code block containing the instances !!!
*/
object EnumerationMacros {
  def sealedInstancesOf[A]: TreeSet[A] = macro sealedInstancesOf_impl[A]

  def sealedInstancesOf_impl[A: c.WeakTypeTag](c: blackbox.Context) = {
    import c.universe._

    val symbol = weakTypeOf[A].typeSymbol.asClass

    if  (!symbol.isClass || !symbol.isSealed)
      c.abort(c.enclosingPosition, "Can only enumerate values of a sealed trait or class.")
    else {

      val children = symbol.knownDirectSubclasses.toList

      if (!children.forall(_.isModuleClass)) c.abort(c.enclosingPosition, "All children must be objects.")
      else c.Expr[TreeSet[A]] {

        def sourceModuleRef(sym: Symbol) = Ident(sym.asInstanceOf[scala.reflect.internal.Symbols#Symbol
          ].sourceModule.asInstanceOf[Symbol]
        )

        Apply(
          Select(
            reify(TreeSet).tree,
            TermName("apply")
          ),
          children.map(sourceModuleRef(_))
        )
      }
    }
  }
}


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow