[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)
}
내가 원하는 것은 열거 값으로 구현을 제공하여 자바에서 수행 할 수 있습니다. 스칼라에 해당하는이 있습니까?
해결법
-
==============================
1.당신이 컴파일러가 알고있는 정보에 대한 액세스를 원하지만, 노출되지 않으며, 매크로는 당신에게 내부 들여다 할 수있는 (합리적) 쉬운 방법을 제공 : 이것은 내 의견으로는 실제로 2.10 매크로에 대한 적절한 사용 사례입니다. 관련 여기 내 대답을 참조하십시오 (하지만 지금은 약간 아웃 오브 날짜) 예를 들어, 아니면 그냥 이런 식으로 뭔가를 사용 :
당신이 컴파일러가 알고있는 정보에 대한 액세스를 원하지만, 노출되지 않으며, 매크로는 당신에게 내부 들여다 할 수있는 (합리적) 쉬운 방법을 제공 : 이것은 내 의견으로는 실제로 2.10 매크로에 대한 적절한 사용 사례입니다. 관련 여기 내 대답을 참조하십시오 (하지만 지금은 약간 아웃 오브 날짜) 예를 들어, 아니면 그냥 이런 식으로 뭔가를 사용 :
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)
그리고 이것은 등 모두 완벽하게 안전, 지저분 당신이 봉인되지 않은 유형의 값을 요구하는 경우 컴파일 타임 오류가 발생,이 개체가 아닌 아이들이다
-
==============================
2.스칼라 매크로에 따라 위에서 언급 한 솔루션은 잘 작동합니다. 그러나이 같은 사례를하지 않습니다 :
스칼라 매크로에 따라 위에서 언급 한 솔루션은 잘 작동합니다. 그러나이 같은 사례를하지 않습니다 :
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.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 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(_)) ) } } } }
-
==============================
3.기본적으로이에 대한 기능은 없습니다. 대신 경우의 당신이 당신의 밀봉 특성의 서브 클래스로 실제 수업을했다 객체보다 일반적인 경우에 이해가되지 것입니다. 귀하의 경우가 더 열거에 의해 처리 될 수있는 것 같습니다
기본적으로이에 대한 기능은 없습니다. 대신 경우의 당신이 당신의 밀봉 특성의 서브 클래스로 실제 수업을했다 객체보다 일반적인 경우에 이해가되지 것입니다. 귀하의 경우가 더 열거에 의해 처리 될 수있는 것 같습니다
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
-
==============================
4.볼품 2.1.0-SNAPSHOT 현재 @ TravisBrown의 질문을 살펴보십시오 코드를 자신의 질문 작품에 게시하고 통과 할 수있는 열거 ADT 요소 세트를 생성합니다. 내가 참조의 편의를 위해 여기에 자신의 솔루션을 다시 덮습니다 (fetchAll은 :-) 광산의 일종이다)
볼품 2.1.0-SNAPSHOT 현재 @ TravisBrown의 질문을 살펴보십시오 코드를 자신의 질문 작품에 게시하고 통과 할 수있는 열거 ADT 요소 세트를 생성합니다. 내가 참조의 편의를 위해 여기에 자신의 솔루션을 다시 덮습니다 (fetchAll은 :-) 광산의 일종이다)
import shapeless._ trait AllSingletons[A, C <: Coproduct] { def values: List[A] } object AllSingletons { implicit def cnilSingletons[A]: AllSingletons[A, CNil] = new AllSingletons[A, CNil] { def values = Nil } implicit def coproductSingletons[A, H <: A, T <: Coproduct](implicit tsc: AllSingletons[A, T], witness: Witness.Aux[H] ): AllSingletons[A, H :+: T] = new AllSingletons[A, H :+: T] { def values: List[A] = witness.value :: tsc.values } } trait EnumerableAdt[A] { def values: Set[A] } object EnumerableAdt { implicit def fromAllSingletons[A, C <: Coproduct](implicit gen: Generic.Aux[A, C], singletons: AllSingletons[A, C] ): EnumerableAdt[A] = new EnumerableAdt[A] { def values: Set[A] = singletons.values.toSet } } def fetchAll[T](implicit ev: EnumerableAdt[T]):Set[T] = ev.values
-
==============================
5.다른 스레드에서이 대답을 참조하십시오. Lloydmetas Enumeratum 라이브러리는 상대적으로 작은 보일러와 쉽게 가능한 패키지의 기능과 같은 자바 열거를 제공합니다.
다른 스레드에서이 대답을 참조하십시오. Lloydmetas Enumeratum 라이브러리는 상대적으로 작은 보일러와 쉽게 가능한 패키지의 기능과 같은 자바 열거를 제공합니다.
-
==============================
6.또한 문제를 해결할 수 있습니다 뭔가 대신 밀봉 특성 반복의, 열거에 방법을 추가하는 암시 적 변환을 추가 할 수있는 가능성이다.
또한 문제를 해결할 수 있습니다 뭔가 대신 밀봉 특성 반복의, 열거에 방법을 추가하는 암시 적 변환을 추가 할 수있는 가능성이다.
object SharingPermission extends Enumeration { val READ = Value("READ") val WRITE = Value("WRITE") val MANAGE = Value("MANAGE") } /** * Permits to extend the enum definition and provide a mapping betweet SharingPermission and ActionType * @param permission */ class SharingPermissionExtended(permission: SharingPermission.Value) { val allowRead: Boolean = permission match { case SharingPermission.READ => true case SharingPermission.WRITE => true case SharingPermission.MANAGE => true } val allowWrite: Boolean = permission match { case SharingPermission.READ => false case SharingPermission.WRITE => true case SharingPermission.MANAGE => true } val allowManage: Boolean = permission match { case SharingPermission.READ => false case SharingPermission.WRITE => false case SharingPermission.MANAGE => true } def allowAction(actionType: ActionType.Value): Boolean = actionType match { case ActionType.READ => allowRead case ActionType.WRITE => allowWrite case ActionType.MANAGE => allowManage } } object SharingPermissionExtended { implicit def conversion(perm: SharingPermission.Value): SharingPermissionExtended = new SharingPermissionExtended(perm) }
from https://stackoverflow.com/questions/13671734/iteration-over-a-sealed-trait-in-scala by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 어떻게 풍부하게 - 내 라이브러리 스칼라 컬렉션에 패턴을 적용합니까? (0) | 2019.10.30 |
---|---|
[SCALA] 스칼라 : 제네릭 대 추상은 유형 (0) | 2019.10.30 |
[SCALA] 어떻게 스칼라에서 implicits 체인 수 있습니까? (0) | 2019.10.30 |
[SCALA] 어떻게 정의하고 스파크 SQL에서 사용자 정의 집계 함수를 사용하는 방법? (0) | 2019.10.30 |
[SCALA] 어떻게하게 IntelliJ IDEA와 함께 SBT를 사용하여 동네 짱의 JAR (지방 JAR)을 구축? (0) | 2019.10.30 |