Reputation: 17648
In a scala program I've created a case to match a user, following some snippets from http://danielwestheide.com/blog/2012/11/21/the-neophytes-guide-to-scala-part-1-extractors.html
In particular, I have declared a class extending another class, and then I've attempted to case match against that class.
user match {
case FreeUser(name) => "Hello " + name;
case PremiumUser(name) => "hello " + name;
}
These operations both fail: it seems as though the case clause doesn't see the class definitions for the FreeUser and PremiumUser classes, which are immediately above it.
class FreeUser(val name: String) extends User{
def unapply(user: FreeUser):Option[String] = Some(user.name);
}
//takes the object as input, returns the parameter used to construct it.
class PremiumUser(val name: String) extends User {
def unapply(user: PremiumUser):Option[String]= Some(user.name);
}
val name = "ASDF"
val user: User = new PremiumUser("jay");
user match {
/** This statement fails to comiple : not found, value FreeUser. **/
case FreeUser(name) => "Hello " + name;
case PremiumUser(name) => "hello " + name;
}
For the full class, you can reference this gist. https://gist.github.com/anonymous/e96107f91ef0262f3268
My question is, thus, simply how to reference an inner class in a case clause in Scala.
Upvotes: 1
Views: 400
Reputation: 1846
both freeUser and the PreimumUser classes should be case classes as follows;
/**
* Why does FreeUser fail to compile?
*/
object Sytax {
object Thrice {
def apply(x : Int) : Int = x *3
def unapply(z : Int) : Option[Int] = if (z%3==0) Some(z/3) else None
}
val x = Thrice(3);
trait User {
def name:String;
}
case class FreeUser(val name: String) extends User{
def unapply(user: FreeUser):Option[String] = Some(user.name);
}
//takes the object as input, returns the parameter used to construct it.
case class PremiumUser(val name: String) extends User {
def unapply(user: PremiumUser):Option[String]= Some(user.name);
}
val name = "ASDF"
val user: User = new PremiumUser("jay");
user match {
case FreeUser(name) => "Hello " + name;
case PremiumUser(name) => "hello " + name;
}
}
Upvotes: 4
Reputation: 15783
The unapply method must be defined in the companion object:
object FreeUser {
def unapply(user: FreeUser):Option[String] = Some(user.name);
}
object PremiumUser {
def unapply(user: PremiumUser):Option[String]= Some(user.name);
}
I can't find at the moment something official about why you can't have unapply in classes, I think it's because matching on classes implicitly calls SomeObject.unapply
and to do so it can't be a class (you'll have to do new SomeClass.unapply
, with a singleton is much better).
Upvotes: 2