我只是想知道是否可以迭代 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 中有等效的吗?
最佳答案
在我看来,这实际上是 2.10 宏的一个合适的用例:您想要访问您知道编译器拥有但未公开的信息,并且宏为您提供了一种(相当)简单的方法来查看内部情况。看我的回答here对于相关的(但现在有点过时)示例,或者只是使用类似这样的内容:
import language.experimental.macros
import scala.reflect.macros.Context
object 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)
这一切都是完全安全的 - 如果您请求未密封、具有非对象子代等类型的值,您将收到编译时错误。
关于scala - Scala 中密封特征的迭代?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13671734/