스칼라에는 enum
Java와 같은 유형 안전 기능이 없습니다 . 관련 상수 세트가 주어지면 스칼라에서 이러한 상수를 나타내는 가장 좋은 방법은 무엇입니까?
답변
http://www.scala-lang.org/docu/files/api/scala/Enumeration.html
사용 예
object Main extends App {
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
def isWorkingDay(d: WeekDay) = ! (d == Sat || d == Sun)
WeekDay.values filter isWorkingDay foreach println
}
답변
나는 예라고한다 스칼라 문서 밖으로 복사 에 의해 skaffman은 위의 연습에 제한 유틸리티입니다 (당신 수도뿐만 아니라 사용 case object
의).
Java와 가장 유사한 것을 얻으려면 Enum
(예를 들어 현명 toString
하고 valueOf
메소드가있는-아마도 enum 값을 데이터베이스에 유지하는 경우) 약간 수정해야합니다. skaffman 의 코드를 사용한 경우 :
WeekDay.valueOf("Sun") //returns None
WeekDay.Tue.toString //returns Weekday(2)
다음 선언을 사용하는 반면 :
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon = Value("Mon")
val Tue = Value("Tue")
... etc
}
더 합리적인 결과를 얻습니다.
WeekDay.valueOf("Sun") //returns Some(Sun)
WeekDay.Tue.toString //returns Tue
답변
여러 가지 방법이 있습니다.
1) 기호를 사용하십시오. 그러나 기호가 필요한 기호가 아닌 기호를 허용하지 않는 한 유형 안전성을 제공하지는 않습니다. 나는 여기서 완전성을 위해 언급하고 있습니다. 사용 예는 다음과 같습니다.
def update(what: Symbol, where: Int, newValue: Array[Int]): MatrixInt =
what match {
case 'row => replaceRow(where, newValue)
case 'col | 'column => replaceCol(where, newValue)
case _ => throw new IllegalArgumentException
}
// At REPL:
scala> val a = unitMatrixInt(3)
a: teste7.MatrixInt =
/ 1 0 0 \
| 0 1 0 |
\ 0 0 1 /
scala> a('row, 1) = a.row(0)
res41: teste7.MatrixInt =
/ 1 0 0 \
| 1 0 0 |
\ 0 0 1 /
scala> a('column, 2) = a.row(0)
res42: teste7.MatrixInt =
/ 1 0 1 \
| 0 1 0 |
\ 0 0 0 /
2) 수업 이용 Enumeration
:
object Dimension extends Enumeration {
type Dimension = Value
val Row, Column = Value
}
또는 직렬화하거나 표시해야하는 경우 :
object Dimension extends Enumeration("Row", "Column") {
type Dimension = Value
val Row, Column = Value
}
이것은 다음과 같이 사용될 수 있습니다 :
def update(what: Dimension, where: Int, newValue: Array[Int]): MatrixInt =
what match {
case Row => replaceRow(where, newValue)
case Column => replaceCol(where, newValue)
}
// At REPL:
scala> a(Row, 2) = a.row(1)
<console>:13: error: not found: value Row
a(Row, 2) = a.row(1)
^
scala> a(Dimension.Row, 2) = a.row(1)
res1: teste.MatrixInt =
/ 1 0 0 \
| 0 1 0 |
\ 0 1 0 /
scala> import Dimension._
import Dimension._
scala> a(Row, 2) = a.row(1)
res2: teste.MatrixInt =
/ 1 0 0 \
| 0 1 0 |
\ 0 1 0 /
불행히도, 모든 경기가 설명되는 것은 아닙니다. 일치하는 행이나 열을 잊어 버린 경우 스칼라 컴파일러는 경고하지 않았을 것입니다. 그래서 그것은 나에게 약간의 유형의 안전을하지만만큼 얻을 수 없습니다.
3) 케이스 객체 :
sealed abstract class Dimension
case object Row extends Dimension
case object Column extends Dimension
이제에 사례를 남기지 않으면 match
컴파일러에서 경고합니다.
MatrixInt.scala:70: warning: match is not exhaustive!
missing combination Column
what match {
^
one warning found
그것은 거의 같은 방식으로 사용되며 심지어 필요하지 않습니다 import
:
scala> val a = unitMatrixInt(3)
a: teste3.MatrixInt =
/ 1 0 0 \
| 0 1 0 |
\ 0 0 1 /
scala> a(Row,2) = a.row(0)
res15: teste3.MatrixInt =
/ 1 0 0 \
| 0 1 0 |
\ 1 0 0 /
그렇다면 왜 케이스 객체 대신 Enumeration을 사용하는지 궁금 할 것입니다. 실제로 케이스 객체는 여기와 같이 여러 번 장점이 있습니다. 그러나 Enumeration 클래스에는 반복자,지도, flatMap, 필터 등을 반환하는 요소 (Scala 2.8의 반복자)와 같은 많은 Collection 메소드가 있습니다.
이 답변은 본질적으로 내 블로그 의이 기사 에서 선택한 부분입니다 .
답변
명명 된 열거를 선언하는 약간 덜 장황한 방법 :
object WeekDay extends Enumeration("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat") {
type WeekDay = Value
val Sun, Mon, Tue, Wed, Thu, Fri, Sat = Value
}
WeekDay.valueOf("Wed") // returns Some(Wed)
WeekDay.Fri.toString // returns Fri
물론 여기서 문제는 이름과 val의 순서를 동기화하여 유지해야한다는 것인데, name과 val이 같은 줄에 선언되어 있으면 더 쉽습니다.
답변
열거 대신 봉인 된 추상 클래스를 사용할 수 있습니다. 예를 들면 다음과 같습니다.
sealed abstract class Constraint(val name: String, val verifier: Int => Boolean)
case object NotTooBig extends Constraint("NotTooBig", (_ < 1000))
case object NonZero extends Constraint("NonZero", (_ != 0))
case class NotEquals(x: Int) extends Constraint("NotEquals " + x, (_ != x))
object Main {
def eval(ctrs: Seq[Constraint])(x: Int): Boolean =
(true /: ctrs){ case (accum, ctr) => accum && ctr.verifier(x) }
def main(args: Array[String]) {
val ctrs = NotTooBig :: NotEquals(5) :: Nil
val evaluate = eval(ctrs) _
println(evaluate(3000))
println(evaluate(3))
println(evaluate(5))
}
}
답변
방금 enumeratum을 발견했습니다 . 그것은 꽤 놀랍고 똑같이 놀랍습니다. 더 잘 알려져 있지 않습니다!
답변
스칼라의 “enumerations”에 관한 모든 옵션에 대한 광범위한 연구를 한 후,이 도메인에 대한 훨씬 더 완전한 개요를 다른 StackOverflow 스레드 에 게시했습니다 . 여기에는 JVM 클래스 / 개체 초기화 순서 문제를 해결 한 “밀봉 된 특성 + 사례 개체”패턴에 대한 솔루션이 포함되어 있습니다.