복붙노트

[SCALA] 어떻게 스칼라에 열거하는 방법을 추가?

SCALA

어떻게 스칼라에 열거하는 방법을 추가?

당신이 할 수 자바에서 :

public enum Enum {
    ONE {
        public String method() {
            return "1";
        }
    },
    TWO {
        public String method() {
            return "2";
        }
    },
    THREE {
        public String method() {
            return "3";
        }
    };

    public abstract String method();
}

당신은 어떻게 스칼라에서이 작업을 수행합니까?

EDIT / 유용한 링크 :

해결법

  1. ==============================

    1.여기 Enumeration.Val 클래스를 확장하여 스칼라 열거 속성을 추가의 예이다.

    여기 Enumeration.Val 클래스를 확장하여 스칼라 열거 속성을 추가의 예이다.

    object Planet extends Enumeration { 
       protected case class Val(val mass: Double, val radius: Double) extends super.Val { 
         def surfaceGravity: Double = Planet.G * mass / (radius * radius) 
         def surfaceWeight(otherMass: Double): Double = otherMass * surfaceGravity 
       } 
       implicit def valueToPlanetVal(x: Value) = x.asInstanceOf[Val] 
    
       val G: Double = 6.67300E-11 
       val Mercury = Val(3.303e+23, 2.4397e6) 
       val Venus   = Val(4.869e+24, 6.0518e6) 
       val Earth   = Val(5.976e+24, 6.37814e6) 
       val Mars    = Val(6.421e+23, 3.3972e6) 
       val Jupiter = Val(1.9e+27, 7.1492e7) 
       val Saturn  = Val(5.688e+26, 6.0268e7) 
       val Uranus  = Val(8.686e+25, 2.5559e7) 
       val Neptune = Val(1.024e+26, 2.4746e7) 
    } 
    
    scala> Planet.values.filter(_.radius > 7.0e6) 
    res16: Planet.ValueSet = Planet.ValueSet(Jupiter, Saturn, Uranus, Neptune) 
    
  2. ==============================

    2.크리스 '솔루션을 구축, 당신은 암시 적 변환 다소 더 좋은 구문을 달성 할 수있다 :

    크리스 '솔루션을 구축, 당신은 암시 적 변환 다소 더 좋은 구문을 달성 할 수있다 :

    object Suit extends Enumeration {
       val Clubs, Diamonds, Hearts, Spades = Value
    
       class SuitValue(suit: Value) {
          def isRed = !isBlack
          def isBlack = suit match {
             case Clubs | Spades => true
             case _              => false
          }
       }
    
       implicit def value2SuitValue(suit: Value) = new SuitValue(suit)
    } 
    

    그럼 당신은, 예를 들어, Suit.Clubs.isRed를 호출 할 수 있습니다.

  3. ==============================

    3.스칼라 열거 자바 열거에서 구별된다.

    스칼라 열거 자바 열거에서 구별된다.

    지금이 순간, (제정신이 방법에서) 그것을 할 수있는 방법의 추가 방법이 없습니다. 일부 작업 어라운드하지만 모든 경우에 작동하고 구문 쓰레기처럼 보이지 않는 것도 있습니다.

    나는 "((런타임에 새로운 인스턴스를 생성 할 수있는 및 객체와 클래스의 새 인스턴스 사이에 작업 등가 관계를 가지면서, 클래스의 열거 된 인스턴스에 메서드를 추가) 뭔가 비슷한 시도했지만 버그 # 4023에 의해 중단되었다 getClasses은 / getDeclaredClasses는 일부 (REPL) 또는 모든 (scalac) 클래스 (객체) 선언 ")를 그리워하는 것 같다.

    내게로 이러한 관련 질문에서보세요 :

    솔직히 열거를 사용하지 않을 것입니다. 이 스칼라 1.0 (2004)에서 클래스 원산지이며 (그것을 쓴 사람을 제외하고) 거기에 이상한 물건 많은없는 사람이 먼저 튜토리얼없이 사용하는 방법을 이해한다.

    나는 절대적으로 열거를 필요로한다면 난 그냥 자바 클래스를 작성합니다.

  4. ==============================

    4.당신이 열거 값을 반복하는 것을 필요로하거나 다른 열거 틱 물건을하지 않으면, 내가 대신 열거의 ADT를을 사용하여 조언을 것입니다.

    당신이 열거 값을 반복하는 것을 필요로하거나 다른 열거 틱 물건을하지 않으면, 내가 대신 열거의 ADT를을 사용하여 조언을 것입니다.

    sealed abstract class Enum {
      def method: String = this match {
        case One => "1"
        case Two => "2"
        case Three => "3"
      }
    }
    case object One extends Enum
    case object Two extends Enum
    case object Three extends Enum
    

    이 방법을 사용하면 일치 식에 하나 또는 그 이상의 사건을 잊지 때 컴파일러가 경고 것을 열거를 통해 하나의 장점이 있습니다.

  5. ==============================

    5.암시 적 클래스를 사용하여, 아론의 솔루션, 스칼라 2.10에서 더욱 컴팩트 한 형태의 정교화 :

    암시 적 클래스를 사용하여, 아론의 솔루션, 스칼라 2.10에서 더욱 컴팩트 한 형태의 정교화 :

    object Suit extends Enumeration {
       val Clubs, Diamonds, Hearts, Spades = Value
    
       implicit class SuitValue(suit: Value) {
          def isRed = !isBlack
          def isBlack = suit match {
             case Clubs | Spades => true
             case _              => false
          }
       }
    } 
    

    다음은 다음과 같이 사용할 수 있습니다 : Suit.Clubs.isRed를

  6. ==============================

    6.이 작업을 수행 할 수 있습니다 :

    이 작업을 수행 할 수 있습니다 :

    object Suit extends Enumeration {
      val Clubs, Diamonds, Hearts, Spades = Value
    
      def isRed(suit : Value) = !isBlack(suit)
      def isBlack(suit : Value) = suit match {
        case Clubs | Spades => true
        case _              => false
      }
    }
    

    분명히 이것은 완벽하지 않습니다하지만 당신은 할 수 있습니다 :

    Suit.isBlack(Suit.Clubs)
    
  7. ==============================

    7.스칼라의 열거 속성 및 / 또는 방법이 열거 형의 값에 추가 할 수 없습니다. 이 새로운 MyEnumeration로 다음을 수행 할 수 있습니다.

    스칼라의 열거 속성 및 / 또는 방법이 열거 형의 값에 추가 할 수 없습니다. 이 새로운 MyEnumeration로 다음을 수행 할 수 있습니다.

    abstract class MyEnumeration {
      // "Value" must be the name of the class defining your values type Value
      type Value
    
      // Contains your values in definition order
      private val vals = collection.mutable.LinkedHashMap[String, Value]()
    
      // A mixin for your values class to automatically collect the values
      protected trait ValuesCollector { self: Value =>
        private val ordinal = vals.size
    
        vals += (fieldNames(ordinal) -> self)
    
        def getName = fieldNames(ordinal)
        override def toString = getName
      }
    
      def apply(ordinal: Int) = vals(fieldNames(ordinal))
      def apply(fldName: String) = vals(fldName)
    
      def values = vals.values
      def namedValues: collection.Map[String, Value] = vals
    
      // Getting the field names through reflection.
      // Copied from scala.Enumeration
      private val fieldNames = getClass.getMethods filter (m =>
        m.getParameterTypes.isEmpty &&
        classOf[ValuesCollector].isAssignableFrom(m.getReturnType) &&
        m.getDeclaringClass != classOf[MyEnumeration]) map (_.getName)
    
    }
    

    여기 스칼라에있는 행성의 예를 참조하십시오.

    object Planet extends MyEnumeration {
    
      case class Value(val mass: Double, val radius: Double) extends ValuesCollector {
        // universal gravitational constant  (m3 kg-1 s-2)
        private val G = 6.67300E-11;
    
        def surfaceGravity = G * mass / (radius * radius)
        def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity
    
      }
    
      val MERCURY = Value(3.303e+23, 2.4397e6)
      val VENUS = Value(4.869e+24, 6.0518e6)
      val EARTH = Value(5.976e+24, 6.37814e6)
      val MARS = Value(6.421e+23, 3.3972e6)
      val JUPITER = Value(1.9e+27, 7.1492e7)
      val SATURN = Value(5.688e+26, 6.0268e7)
      val URANUS = Value(8.686e+25, 2.5559e7)
      val NEPTUNE = Value(1.024e+26, 2.4746e7)
      val PLUTO = Value(1.27e+22, 1.137e6)
    
    }
    
    object PlanetTest {
      def main(args: Array[String]) {
        val earthWeight = 175
        val mass = earthWeight/Planet.EARTH.surfaceGravity
        for (p <- Planet.values) println("Your weight on %s is %f" format (p, p.surfaceWeight(mass)))
        /* Your weight on MERCURY is 66.107583
         * Your weight on VENUS is 158.374842
         * Your weight on EARTH is 175.000000
         * Your weight on MARS is 66.279007
         * Your weight on JUPITER is 442.847567
         * Your weight on SATURN is 186.552719
         * Your weight on URANUS is 158.397260
         * Your weight on NEPTUNE is 199.207413
         * Your weight on PLUTO is 11.703031
         */
      }
    
    } 
    
  8. ==============================

    8.

    object Unit extends Enumeration {
      abstract class UnitValue(var name: String) extends Val(name) {
        def m: Unit
      }
      val G = new UnitValue("g") {
        def m {
            println("M from G")
        }
      }
      val KG = new UnitValue("kg") {
        def m {
            println("M from KG")
        }
      }
    }
    
  9. ==============================

    9.scala.Enumeration의 소스 코드를 체크 아웃 후, 나는이있어 :

    scala.Enumeration의 소스 코드를 체크 아웃 후, 나는이있어 :

    
    object MyEnum extends Enumeration {
      val ONE = new Val { def method = "1" }
      val TWO = new Val { def method = "2" }
      val THREE = new Val { def method = "3" }
    }
    

    그것은 익명의 클래스가 사용되기 때문에 '새'를 제거하기 어려운 것 같다. 누구나 할 방법을 알고 있으면 알려주세요 :)

  10. ==============================

    10.당신이 절대적으로 열거 값과 값을 반복 할 수 있어야 당 방법을해야하는 경우, 당신은 이런 식으로 뭔가를 할 수 있습니다 :

    당신이 절대적으로 열거 값과 값을 반복 할 수 있어야 당 방법을해야하는 경우, 당신은 이런 식으로 뭔가를 할 수 있습니다 :

    object BatchCategory extends Enumeration {
      class BatchCategory extends Val {
        val isOfficial, isTest, isUser = false
      }
    
      val OFFICIAL = new BatchCategory { override val isOfficial = true }
      val TEST =     new BatchCategory { override val isTest = true }
      val USER =     new BatchCategory { override val isUser = true }
    
      // Needed to get BatchCategory from Enumeration.values
      implicit def valueToBatchCategory(v: Value): BatchCategory = v match {
        case bc: BatchCategory => bc
        case x => throw new IllegalArgumentException("Value is not a BatchCategory: " + x)
      }
    
      def valueOf(catStr: String): BatchCategory = {
        BatchCategory.values.
          find { v => val s = v.toString; s.take(1) == catStr || s == catStr }.
          getOrElse(throw new IllegalArgumentException("Unknown category '" + catStr + "' !  "))
      }
    
      def main(args: Array[String]) {
        BatchCategory.values.foreach(v => println(v + " isOfficial=" + v.isOfficial))
      }
    }
    

    인쇄물

    OFFICIAL isOfficial=true
    TEST isOfficial=false
    USER isOfficial=false
    

    이것은 열거 외에 온건 열거 전략으로 이동할 수 없습니다 일부 레거시 코드에 대해 이루어졌다.

  11. ==============================

    11.스칼라 열거가 인수 / 방법 - 사용자 정의 값을 지원하지 않는 것을 말한다 대답은 잘못된 것 같다. 기타 답변 (그들 중 일부는 암시 포함)가 할 수있는 것을 증명하지만 그들은 이름 중복을 요구하는 인상을 : 당신의 값이 두 번째로, 이름이 요점 반면 문자열로 값 생성자에 공급되고, 자바 객체 필드로 이름을 선언했다 열거 형의 중복없이 할 수있는 반복 가능한 이름 -> 값 맵 및 스칼라를 만드는 것입니다 :

    스칼라 열거가 인수 / 방법 - 사용자 정의 값을 지원하지 않는 것을 말한다 대답은 잘못된 것 같다. 기타 답변 (그들 중 일부는 암시 포함)가 할 수있는 것을 증명하지만 그들은 이름 중복을 요구하는 인상을 : 당신의 값이 두 번째로, 이름이 요점 반면 문자열로 값 생성자에 공급되고, 자바 객체 필드로 이름을 선언했다 열거 형의 중복없이 할 수있는 반복 가능한 이름 -> 값 맵 및 스칼라를 만드는 것입니다 :

    object Ops1 extends Enumeration {
    
        protected case class OpsVal(f: Int => Int) extends super.Val(/*nextId*/)
    
        val ZERO = new FuncVal (x => 0)
        val DOUBLE = new FuncVal (x => 2 * x )
    
        implicit def convert(v: Value) = v.asInstanceOf[OpsVal]
    
    }
    
    // implicit is not needed
    Ops1.ZERO.f(1)                            //> res0: Int = 0
    
    // implicit is needed
    Ops1.values map (v => (v + "=>" + v.f(1)))//> res1: scala.collection.immutable.SortedSet[String] = TreeSet(DOUBLE=>2, ZERO=>0)
    

    나는 위의 더 간결가보다라고 생각합니다

    object Ops2 extends Enumeration {
    
        protected abstract class OpsVal extends Val() {
          def f(a: Int): Int
        }
    
        val ZERO = new OpsVal { def f(x: Int) = 0 }
        val DOUBLE = new OpsVal { def f(x: Int) = 2 * x }
    
        implicit def convert(valu: Value) = valu.asInstanceOf[OpsVal]
    }
    Ops2.ZERO.f(1) // implicit is not needed  //> res2: Int = 0
    
    // implicit is needed
    Ops2_3.values map (v => (v, v(1)))        //> res7: scala.collection.immutable.SortedSet[(e.Ops2_3.Value, Int)] = TreeSet
                                                  //| ((ZERO,0), (DOUBLE,2))
    

    값 당 하나의 방법이 있기 때문에, 우리는 함수로 변환 할 수 있습니다

    object Ops2_3 extends Enumeration {
    
        protected case class FuncVal(f: Int => Int) extends Val {
            def apply(x: Int) = f(x) // no need to extend Function1 explicitly
        }
    
        val ZERO = new FuncVal (x => 0)
        val DOUBLE = new FuncVal (x => 2 * x )
    
        implicit def convert(v: Value) = v.asInstanceOf[FuncVal]
    
    }
    Ops2_3.ZERO(1) // implicit is not needed  //> res6: Int = 0
    
    // implicit is needed
    Ops2_3.values map (v => (v, v(1)))        //> res7: scala.collection.immutable.SortedSet[(e.Ops2_3.Value, Int)] = TreeSet
                                                  //| ((ZERO,0), (DOUBLE,2))
    

    모든 값 공유 기능은, 다음과 같이 정의 할 수 있습니다 (가능한에서 인수 파서)

    val args: Array[String] = "-silent -samples 100 -silent ".split(" +").toArray
                                                  //> args  : Array[String] = Array(-silent, -samples, 100, -silent)
    object Opts extends Enumeration {
    
        val nopar, silent, samples = new Val() {
            def apply() = args.contains(toString)
            def asInt(default: Int) = { val i = args.indexOf(toString) ;  if (i == -1) default else args(i+1).toInt}
            def asInt: Int = asInt(-1)
            override def toString = "-" + super.toString
        }
    }
    
    Opts.nopar()                              //> res0: Boolean = false
    Opts.samples.asInt                        //> res1: Int = 100
    

    다른 사용자는 스칼라의 밀봉 특성을 통해 밀봉 특성 + 매크로, 반복의 경우에 주장?

  12. from https://stackoverflow.com/questions/4346580/how-to-add-a-method-to-enumeration-in-scala by cc-by-sa and MIT license