4

私は Scala でいくつかの単純なデータ構造とコレクションを扱っていますが、奇妙な動作だと思うことに気付きました。オブジェクトは次のとおりです。

class State (protected val trackmap: Map[Int, List[String]]) {

  override def clone : State = {
    new State(Map() ++ trackmap)
  }

  override def toString = { "State: " + trackmap.toString }

  def equals (other: State) : Boolean = {
    //println("Comparing " + trackmap + " to " + other.trackmap)
    trackmap == other.trackmap  

  }

  def == (other: State) : Boolean = {
    this equals other
  }
}

そして私の関連テスト:

  test("state equality") {
    val state = new State( Map(1 -> List("engine"), 2 -> List("a"), 3 -> List("b")) )

    expect(true) { state equals state.clone }
    expect(true) { state == state.clone }
    expect(false) { state == new State(Map(1 -> List("a"))) }
    expect(false) { state equals new State(Map(1 -> List("a"))) }

    expect(true) { List(state).exists( _.equals (state.clone) )}
    expect(true) { List(state).exists( _.== (state.clone) )}
    expect(true) { List(state).contains( state.clone )}
  }

合格するはずの最後のものを除いて、それらはすべて合格します。Scala のソースは見ていませんが、contains は基本的に 2 番目の exists 呼び出しとして実装されると思います。

4

3 に答える 3

12

Scalaの実際のequalsメソッドをオーバーライドしていないので、奇妙な動作をします。equalsメソッドを次のように書き直してください。そうすれば、うまくいくはずです。

override def equals (other: Any) : Boolean = {
    other match{
      case that: State =>
        //println("Comparing " + trackmap + " to " + other.trackmap)
        trackmap == that.trackmap
      case _ => false
    }
}

overrideほら、ScalaのequalsメソッドはAny not State型のパラメーターを取り、そのためのキーワードを追加する必要があります。

ところで、Scalaは自動的にequalsメソッドに再マップするので、==メソッドも必要ありません!

于 2013-03-07T22:42:08.237 に答える
4

のデフォルトの実装をオーバーライドしなかったため、equalsメソッドは によって呼び出されていません。これの手がかりは、コンパイラが修飾子の欠如について文句を言わないことです。containsAnyoverride

正しいメソッド シグネチャは次のようになります。

override def equals(other: Any): Boolean

を呼び出すとList(state).exists( _.equals (state.clone)、コンパイラは引数の型が であることを知っていたため、実装に解決されましたState。したがって、そのタイプに特化したメソッドのオーバーロードされたバリアントを選択しました。

のシグネチャは、 の型パラメータに関係なく、contains 常に型 の引数を取るため、メソッド呼び出しは の既定の実装に解決されます。AnyListequals

于 2013-03-07T22:41:40.423 に答える
3

equalsandの実装は、==あるべき姿ではありません。そのため、Scala にはcaseクラスがあります。

クラスは次のようになります

case class State(protected val trackmap: Map[Int, List[String]]) {

  override def clone: State = {
    new State(Map() ++ trackmap)
  }

  override def toString = { "State: " + trackmap.toString }
}

それらを手動で実装したい場合は、Equals特性を実装する必要があります。そして、次のメソッドをオーバーライドします。

override def canEqual(other: Any) = 
  other.isInstanceOf[State]

override def equals(other: Any) = {
  other match {
    case that: State => (that canEqual this) && trackmap == that.trackmap
    case _ => false
  }
}

override def hashCode() = {
  val prime = 41
  prime + trackmap.hashCode
}
于 2013-03-07T22:51:08.220 に答える