Orest Ivasiv
Orest Ivasiv

Reputation: 181

Mix several Enumerations into one

Let's assume that we have the next two Enumerations:

object EnumX extends Enumeration {
  val val1 = Value
  val val2 = Value
}

object EnumY extends Enumeration {
  val valA = Value
  val valB = Value
}

These enumerations have similar business value and can't be changed. For some reason I'd like to have "new" type (let's name it MixedEnumXY) which can accept enum values from EnumX and EnumY:

E.g.

val e1: MixedEnumXY = EnumX.val1
val e2: MixedEnumXY = EnumY.valA

Is it possible to implement this in Scala?

Upvotes: 3

Views: 82

Answers (3)

Orest Ivasiv
Orest Ivasiv

Reputation: 181

So, I came up with the next DRAFT solution

object EnumX extends Enumeration {
  val val1 = Value
  val val2 = Value
}

object EnumY extends Enumeration {
  val valA = Value
  val valB = Value
}

sealed trait MixedEnum {
  def reason: Enumeration#Value
  override def toString: String = reason.toString
}

case class EnumXMix(reason: EnumX.Value) extends MixedEnum
case class EnumYMix(reason: EnumY.Value) extends MixedEnum


object MixedEnum {
  implicit def EnumX2MixedEnum(value: EnumX.Value) = EnumXMix(value)
  implicit def EnumY2MixedEnum(value: EnumY.Value) = EnumYMix(value)
}

Now, you can use it the next way:

import MixedEnum._
val enumValue1: MixedEnum = EnumX.val1
val enumValue2: MixedEnum = EnumY.valA
val enumSeq: Seq[MixedEnum] = Seq(EnumX.val1, EnumY.valA)

println(enumValue1)
println(enumValue2) 
println(enumSeq)

Output:

val1
valA
List(val1, valA)

Upvotes: 1

Krzysztof Atłasik
Krzysztof Atłasik

Reputation: 22595

Maybe you can use sealed case classes?

sealed trait XY
sealed trait X extends XY
sealed trait Y extends XY

object EnumX {
    case object Val1 extends X
    case object Val2 extends X
}

object EnumY {
    case object ValA extends Y
    case object ValB extends Y
} 

val e1: XY = EnumX.Val1
val e2: XY = EnumY.ValA

Upvotes: 2

SergGr
SergGr

Reputation: 23788

What you want seems hacky to me so you probably should be OK with a hacky solution that relies on implicit conversions:

object EnumX extends Enumeration {
  val val1 = Value
  val val2 = Value
}

object EnumY extends Enumeration {
  val valA = Value
  val valB = Value
}

import scala.languageFeature.implicitConversions

object MixedEnumXY extends Enumeration {
  val val1 = Value
  val val2 = Value
  val valA = Value
  val valB = Value

  implicit def fromEnumX(ex: EnumX.Value): MixedEnumXY.Value = ex match {
    case EnumX.val1 => val1
    case EnumX.val2 => val2
  }

  implicit def fromEnumY(ey: EnumY.Value): MixedEnumXY.Value = ey match {
    case EnumY.valA => valA
    case EnumY.valB => valB
  }
}

def test(): Unit = {
  val e1: MixedEnumXY.Value = EnumX.val1
  val e2: MixedEnumXY.Value = EnumY.valA
}

The other obvious choice would be to use Either or create a similar custom class with your additional logic.

Upvotes: 1

Related Questions