Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala pattern matching Java enum value

I have my java enum such as: FOO("foo"), BAR("bar") ... and I have a getValue() method to return the value "foo" and "bar" of the enum and this has to be in Java.

On the other hand, I have to match this in Scala:

result match {
  case "foo" =>

I am trying to do:

result match {
  case Enum.FOO.getValue() => 

I get this error:

method getValue is not a case class constructor, nor does it have an
unapply/unapplySeq method

I'm not quite sure what is happening here since my getValue() method returns a String so why I can't use it for pattern matching? Thanks

like image 892
Duc Avatar asked Mar 07 '14 10:03

Duc


People also ask

Does Scala have pattern matching?

Pattern matching is the second most widely used feature of Scala, after function values and closures. Scala provides great support for pattern matching, in processing the messages. A pattern match includes a sequence of alternatives, each starting with the keyword case.

How does Scala pattern matching work?

Pattern matching is a mechanism for checking a value against a pattern. A successful match can also deconstruct a value into its constituent parts. It is a more powerful version of the switch statement in Java and it can likewise be used in place of a series of if/else statements.

Can we use CASE classes in pattern matching?

Case classes help us use the power of inheritance to perform pattern matching. The case classes extend a common abstract class. The match expression then evaluates a reference of the abstract class against each pattern expressed by each case class.


3 Answers

You can pattern match on Java enums, but you can't call methods in the destructuring part of the match. So this works:

j match { case Jenum.FOO => "yay"; case _ => "boo" }

if j is an instance of your Java enum (cleverly labeled Jenum).

You can however do something like this:

"foo" match {
  case s if s == Jenum.FOO.getValue => "yay"
  case _                            => "boo"
}

Or you can convert your string to the enum first:

Jenum.values.find(_.getValue == "foo") match {
  case Some(Jenum.FOO) => "yay"
  case _               => "boo"
}

(you might also want to unwrap the option first to avoid repeating Some(...) so many times).

For reference, this is the test enum I used (Jenum.java):

public enum Jenum {
  FOO("foo"), BAR("bar");

  private final String value;
  Jenum(String value) { this.value = value; }

  public String getValue() { return value; }
}
like image 147
Rex Kerr Avatar answered Oct 19 '22 12:10

Rex Kerr


You can't use a method call result as a pattern. Instead just write

if (result == YourEnum.FOO.getValue()) { 
  ... 
} else if {
  ...
}

or

try {
  val resultAsEnum = YourEnum.valueOf(result)

  resultAsEnum match {
    case YourEnum.FOO => ...
    ...
  }
} catch {
  case e: IllegalArgumentException => // didn't correspond to any value of YourEnum
}
like image 41
Alexey Romanov Avatar answered Oct 19 '22 12:10

Alexey Romanov


You receive the comment "method". So scala does not evaluates your function. It tried to call unapply on method.

You can implement something like (in MyEnum class):

 public static MyEnum fromText(String text) {
        for (MyEnum el : values()) {
            if (el.getValue().equals(text)) {
                return el;
            }
        }
        return null;
    }

And then

MyEnum.fromText("foo") match{
 case FOO => ..
}
like image 36
Andrzej Jozwik Avatar answered Oct 19 '22 12:10

Andrzej Jozwik