开发者

Enums in Scala with multiple constructor parameters

I am writing my first large Scala program. In the Java equivalent, I have an enum that contains labels and tooltips for my UI controls:

public enum ControlText {
  CANCEL_BUTTON("Cancel", "Cancel the changes and dismiss the dialog"),
  OK_BUTTON("OK", "Save the changes and dismiss the dialog"),
  // ...
  ;

  private final String controlText;
  private final String toolTipText;

  ControlText(String controlText, String toolTipText) {
    this.controlText = controlText;
    this.toolTipText = toolTipText;
  }

  public String getControlText() { return controlText; }
  public String getToolTipText() { return toolTipText; }
}

Never mind the wisdom of using enums for this. There are other places that I want to do similar things.

How can I do this in Scala using scala.Enumeration? The Enumerati开发者_JAVA技巧on.Value class takes only one String as a parameter. Do I need to subclass it?

Thanks.


You could do this which matches how enums are used:

sealed abstract class ControlTextBase
case class ControlText(controlText: String, toolTipText: String)
object OkButton extends ControlText("OK", "Save changes and dismiss")
object CancelButton extends ControlText("Cancel", "Bail!")


I'd like to propose the following workaround for the issue:

object ControlText extends Enumeration {

  type ControlText = ControlTextValue

  case class ControlTextValue(controlText: String, toolTipText: String) extends Val(controlText)

  val CANCEL_BUTTON = ControlTextInternalValue("Cancel", "Cancel the changes and dismiss the dialog")
  val OK_BUTTON = ControlTextInternalValue("OK", "Save the changes and dismiss the dialog")

  protected final def ControlTextInternalValue(controlText: String, toolTipText: String): ControlTextValue = {
    ControlTextValue(controlText, toolTipText)
  }    
}

Now you can use ControlText as Java enum:

val c: ControlText
c.toolTipText

The only a little bad smell is to get enum object by withName or apply methods. You have to do a cast:

val c: ControlText = ControlText.withName(name).asInstanceOf[ControlText]


Following on from Mitch's answer, if you find that the sealed behaviour is not restrictive enough in limiting subclassed instances to the file where the base class is defined, you can use an object (module) definition like this:

object ControlTexts {
  sealed abstract class ControlTextBase

  case class ControlText private[ControlTexts] (controlText: String, 
                                                toolTipText: String)
          extends ControlTextBase

  object OkButton     extends ControlText("OK", "Save changes and dismiss")
  object CancelButton extends ControlText("Cancel", "Bail!")
}

which obviously limits further instantiation of ControlText instances. The sealed keyword is still important in helping detect missing cases in pattern matching.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜