亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在Scala中對密封特性進行迭代?

在Scala中對密封特性進行迭代?

HUX布斯 2019-08-27 13:44:41
在Scala中對密封特性進行迭代?我只是想知道是否有可能在Scala中迭代密封的特征?如果沒有,為什么不可能?由于特性是密封的,應該可能沒有?我想做的是這樣的:sealed trait ResizedImageKey {   /**    * Get the dimensions to use on the resized image associated with this key    */   def getDimension(originalDimension: Dimension): Dimension}case class Dimension(width: Int,  height: Int)case object Large extends ResizedImageKey {   def getDimension(originalDimension: Dimension) = Dimension(1000,1000)}case object Medium extends ResizedImageKey{   def getDimension(originalDimension: Dimension) = Dimension(500,500)}case object Small extends ResizedImageKey{   def getDimension(originalDimension: Dimension) = Dimension(100,100)}通過給枚舉值賦予實現,可以在Java中完成我想要的。Scala中有同等的東西嗎?
查看完整描述

3 回答

?
大話西游666

TA貢獻1817條經驗 獲得超14個贊

在我看來,這實際上是2.10宏的一個合適的用例:你想要訪問你知道編譯器有的信息,但是沒有公開,而宏給你一個(合理)簡單的方法來查看內部。請在此處查看我的答案以獲取相關(但現在稍微過時)的示例,或者只使用以下內容:

import language.experimental.macrosimport scala.reflect.macros.Contextobject SealedExample {
  def values[A]: Set[A] = macro values_impl[A]

  def values_impl[A: c.WeakTypeTag](c: Context) = {
    import c.universe._    val symbol = weakTypeOf[A].typeSymbol    if (!symbol.isClass) c.abort(
      c.enclosingPosition,
      "Can only enumerate values of a sealed trait or class."
    ) else if (!symbol.asClass.isSealed) c.abort(
      c.enclosingPosition,
      "Can only enumerate values of a sealed trait or class."
    ) else {
      val children = symbol.asClass.knownDirectSubclasses.toList      if (!children.forall(_.isModuleClass)) c.abort(
        c.enclosingPosition,
        "All children must be objects."
      ) else c.Expr[Set[A]] {
        def sourceModuleRef(sym: Symbol) = Ident(
          sym.asInstanceOf[
            scala.reflect.internal.Symbols#Symbol
          ].sourceModule.asInstanceOf[Symbol]
        )

        Apply(
          Select(
            reify(Set).tree,
            newTermName("apply")
          ),
          children.map(sourceModuleRef(_))
        )
      }
    }
  }}

現在我們可以寫下面的內容:

scala> val keys: Set[ResizedImageKey] = SealedExample.values[ResizedImageKey]keys: Set[ResizedImageKey] = Set(Large, Medium, Small)

這一切都非常安全 - 如果您要求未密封的類型的值,具有非對象子項等,您將獲得編譯時錯誤。


查看完整回答
反對 回復 2019-08-27
?
慕神8447489

TA貢獻1780條經驗 獲得超1個贊

基于Scala Macros的上述解決方案效果很好。然而,它不像以下情況:

sealed trait ImageSize                            object ImageSize {                                
    case object Small extends ImageSize             
    case object Medium extends ImageSize            
    case object Large extends ImageSize             
    val values = SealedTraitValues.values[ImageSize]}

為此,可以使用以下代碼:

import language.experimental.macrosimport scala.reflect.macros.Contextobject SealedExample {
    def values[A]: Set[A] = macro values_impl[A]

    def values_impl[A: c.WeakTypeTag](c: Context) = {
        import c.universe._        val symbol = weakTypeOf[A].typeSymbol        if (!symbol.isClass) c.abort(
            c.enclosingPosition,
            "Can only enumerate values of a sealed trait or class."
        ) else if (!symbol.asClass.isSealed) c.abort(
            c.enclosingPosition,
            "Can only enumerate values of a sealed trait or class."
        ) else {
            val siblingSubclasses: List[Symbol] = scala.util.Try {
                val enclosingModule = c.enclosingClass.asInstanceOf[ModuleDef]
                enclosingModule.impl.body.filter { x =>
                    scala.util.Try(x.symbol.asModule.moduleClass.asClass.baseClasses.contains(symbol))
                        .getOrElse(false)
                }.map(_.symbol)
            } getOrElse {
                Nil
            }

            val children = symbol.asClass.knownDirectSubclasses.toList ::: siblingSubclasses            if (!children.forall(x => x.isModuleClass || x.isModule)) c.abort(
                c.enclosingPosition,
                "All children must be objects."
            ) else c.Expr[Set[A]] {
                def sourceModuleRef(sym: Symbol) = Ident(
                    if (sym.isModule) sym else
                        sym.asInstanceOf[
                            scala.reflect.internal.Symbols#Symbol
                            ].sourceModule.asInstanceOf[Symbol]
                )

                Apply(
                    Select(
                        reify(Set).tree,
                        newTermName("apply")
                    ),
                    children.map(sourceModuleRef(_))
                )
            }
        }
    }}


查看完整回答
反對 回復 2019-08-27
?
MM們

TA貢獻1886條經驗 獲得超2個贊

本機沒有這種能力。在更常見的情況下,沒有意義,而不是案例對象,你有實際的類作為密封特征的子類??雌饋砟愕那闆r可能會被枚舉更好地處理

object ResizedImageKey extends Enumeration {
  type ResizedImageKey = Value
  val Small, Medium, Large = Value
  def getDimension(value:ResizedImageKey):Dimension = 
      value match{
         case Small => Dimension(100, 100)
         case Medium => Dimension(500, 500)
         case Large => Dimension(1000, 1000)}println(ResizedImageKey.values.mkString(",") //prints Small,Medium,Large

或者,您可以自己創建枚舉,為方便起見,可能將其放在伴隨對象中

object ResizedImageKey{
  val values = Vector(Small, Medium, Large)}println(ResizedImageKey.values.mkString(",") //prints Small,Medium,Large


查看完整回答
反對 回復 2019-08-27
  • 3 回答
  • 0 關注
  • 550 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號