Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern matching over non-case class in Scala

Lets assume that I have a plain third party (i.e. I cannot modify it) class defined like:

class Price(var value: Int)

Is this possible to match instances of this class with some patterns?

For example, I want to implement function:

def printPrice(price: Price) = {
    // implementation here
}

... that prints price is {some value} for every price that has value <= 9000 and price is over 9000 in all other cases.

For example, calling:

printPrice(new Price(10))
printPrice(new Price(9001))

should print:

price is 10
price is over 9000

How can I implement printPrice using pattern matching?

like image 950
Eugene Loy Avatar asked Nov 17 '13 14:11

Eugene Loy


Video Answer


2 Answers

You can create custom extractor:

package external {
    class Price(var value: Int)
}

object Price {
    def unapply(price: Price): Option[Int] = Some(price.value)
}

def printPrice(price: Price) = price match {
    case Price(v) if v <= 9000 => println(s"price is $v")
    case _ => println("price is over 9000")
}

printPrice(new Price(10))
printPrice(new Price(9001))

For case classes compiler generates it automaticaly. I think in your case extractors is overkill, but may be it's only simplified sample.

like image 105
Sergey Passichenko Avatar answered Sep 23 '22 14:09

Sergey Passichenko


Thinked about accepting flavian's solution but came up with slightly better one by myself.

Here is how one could implement printPrice (without need to use wrapper objects and modifying original class):

def printPrice(price: Price) = price match {
    case p: Price if (p.value <= 9000) => println("price is " + p.value)
    case p: Price => println("price is over 9000")
}

PS: credits to flavian for showing that you can use if in pattern. Upvoting your answer for this.

like image 35
Eugene Loy Avatar answered Sep 22 '22 14:09

Eugene Loy