问题
I have created a class called CaseInsensitive which wraps a string (see Implementing a string class that does case insensitive comparisions in Scala).
I've created a case class which has a member variable of type CaseInsensitive, so it gets a default unapply method, which extracts a variable of type CaseInsensitive, but I was hoping to use it like this:
case class PropertyKey( val name : CaseInsensitive )
val foo = new PropertyKey("foo")
val result = foo match {
case PropertyKey("foo") => true
case _ => false
}
This code fails to compile: (on the extractor line, not the constructor line)
type mismatch;
found : java.lang.String("foo")
required: com.acme.CaseInsensitive
But I thought my implicit conversions from String to CaseInsensitive would enable this to compile, rather than me having to type the more verbose:
case class PropertyKey( val name : CaseInsensitive )
val foo = new PropertyKey("foo")
val result = foo match {
case PropertyKey(CaseInsensitive("foo")) => true
case _ => false
}
Here is the implementation of CaseInsensitive:
/** Used to enable us to easily index objects by string, case insensitive
*
* Note: this class preserve the case of your string!
*/
case class CaseInsensitive ( val _s : String ) extends Proxy {
require( _s != null)
val self = _s.toLowerCase
override def toString = _s
def i = this // convenience implicit conversion
}
object CaseInsensitive {
implicit def CaseInsensitive2String(c : CaseInsensitive) = if ( c == null ) null else c._s
implicit def StringToCaseInsensitive(s : String) = CaseInsensitive(s)
def fromString( s : String ) = s match {
case null => None
case _ => Some(CaseInsensitive(s))
}
}
回答1:
You could always define a convenience extractor and import it (feel free to use a shorter name):
object PropertyKeyCI {
def unapply(p: PropertyKey): Option[String] = Some(p.name.self)
}
Then, extraction is:
val foo = new PropertyKey("foo")
val result = foo match {
case PropertyKeyCI("foo") => true
case _ => false
}
(Bad Semantics Alert)
Although note that this would match as false for PropertyKeyCI("Foo"), because your "CaseInsensitive" class is really a "LowerCase" class. I say this because it is hard for me to imagine what the desired behavior would be for the unapply() method otherwise. From your case class default, you are returning an Option[String] of the original (unlowercased) string, which gives this unintuitive behavior:
// result == false !!!!
val foo = new CaseInsensitive("Foo")
val result = foo match {
case CaseInsensitive("foo") => true
case _ => false
}
val CaseInsensitive(s) = "aBcDeF"
assertFalse(s == "abcdef")
Awwww.... toss it. Just use DOS.
来源:https://stackoverflow.com/questions/1820777/is-it-possible-to-use-implicit-conversions-for-parameters-to-extractors-unapply