1

文字列をラップする CaseInsensitive というクラスを作成しました (「Scala で大文字と小文字を区別しない比較を行う文字列クラスの実装」を参照)。

CaseInsensitive 型のメンバー変数を持つケース クラスを作成したので、CaseInsensitive 型の変数を抽出するデフォルトの unapply メソッドを取得しますが、次のように使用することを望んでいました。

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))
  }
}
4

1 に答える 1

4

いつでも便利なエクストラクタを定義してインポートできます (短い名前を自由に使用してください)。

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
  }

(悪いセマンティクス アラート)

「CaseInsensitive」クラスは実際には「LowerCase」クラスであるため、これは PropertyKeyCI("Foo") の場合は false と一致することに注意してください。そうでない場合、 unapply() メソッドの望ましい動作がどのようなものになるかを想像するのが難しいため、これを言います。ケースクラスのデフォルトから、元の(小文字化されていない)文字列の Option[String] を返しているため、この非直感的な動作が発生します。

  // 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を使用するだけです。

于 2009-11-30T18:18:02.653 に答える