Можно ли использовать неявные преобразования для параметров в экстракторы (не применять) в Scala?
Я создал класс с именем CaseInsensitive, который переносит строку (см. Реализация класса строки, который выполняет сравнения без учета регистра в Scala).
Я создал класс case, который имеет переменную-член типа CaseInsensitive, поэтому он получает метод по умолчанию unapply, который извлекает переменную типа CaseInsensitive, но я надеялся использовать его следующим образом:
case class PropertyKey( val name : CaseInsensitive )
val foo = new PropertyKey("foo")
val result = foo match {
case PropertyKey("foo") => true
case _ => false
}
Этот код не компилируется: (в строке экстрактора, а не в строке конструктора)
type mismatch;
found : java.lang.String("foo")
required: com.acme.CaseInsensitive
Но я думал, что мои неявные преобразования из String в CaseInsensitive позволят это скомпилировать, а не вводить более подробный текст:
case class PropertyKey( val name : CaseInsensitive )
val foo = new PropertyKey("foo")
val result = foo match {
case PropertyKey(CaseInsensitive("foo")) => true
case _ => false
}
Вот реализация 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 ответ
Вы всегда можете определить удобный экстрактор и импортировать его (не стесняйтесь использовать более короткое имя):
object PropertyKeyCI {
def unapply(p: PropertyKey): Option[String] = Some(p.name.self)
}
Тогда извлечение это:
val foo = new PropertyKey("foo")
val result = foo match {
case PropertyKeyCI("foo") => true
case _ => false
}
(Предупреждение о плохой семантике)
Хотя обратите внимание, что для PropertyKeyCI("Foo") это будет соответствовать значению false, поскольку ваш класс "CaseInsensitive" действительно является классом "LowerCase". Я говорю это потому, что мне трудно представить, каким будет желаемое поведение метода unapply() в противном случае. Из класса по умолчанию для вашего дела вы возвращаете Option[String] исходной (unercercased) строки, которая дает такое неинтуитивное поведение:
// result == false !!!!
val foo = new CaseInsensitive("Foo")
val result = foo match {
case CaseInsensitive("foo") => true
case _ => false
}
val CaseInsensitive(s) = "aBcDeF"
assertFalse(s == "abcdef")
Ааааа.... брось это. Просто используйте DOS.