/* * Copyright (C) 2007-2008 Artima, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Automatically generated Scala interpreter transcript from: * * Programming in Scala (First Edition, Version 6) * by Martin Odersky, Lex Spoon, Bill Venners * * http://booksites.artima.com/programming_in_scala */ scala> class Point(val x: Int, val y: Int) { // An utterly wrong definition of equals def equals(other: Point): Boolean = this.x == other.x && this.y == other.y } defined class Point scala> val p1, p2 = new Point(1, 2) p1: Point = Point@2b723c p2: Point = Point@58d1a4 scala> val q = new Point(2, 3) q: Point = Point@4ecedd scala> p1 equals p2 res0: Boolean = true scala> p1 equals q res1: Boolean = false scala> import scala.collection.mutable._ import scala.collection.mutable._ scala> val coll = HashSet(p1) coll: scala.collection.mutable.Set[Point] = Set(Point@2b723c) scala> coll contains p2 res2: Boolean = false scala> val p2a: Any = p2 p2a: Any = Point@58d1a4 scala> p1 equals p2a res3: Boolean = false scala> class Point(val x: Int, val y: Int) { // A better definition, but still not perfect override def equals(other: Any) = other match { case that: Point => this.x == that.x && this.y == that.y case _ => false } } defined class Point scala> val p1, p2 = new Point(1, 2) p1: Point = Point@3095f4 p2: Point = Point@c4c852 scala> HashSet(p1) contains p2 res4: Boolean = false scala> class Point(var x: Int, var y: Int) { // Problematic override def hashCode = 41 * (41 + x) + y override def equals(other: Any) = other match { case that: Point => this.x == that.x && this.y == that.y case _ => false } } defined class Point scala> val p = new Point(1, 2) p: Point = Point@6bc scala> val coll = HashSet(p) coll: scala.collection.mutable.Set[Point] = Set(Point@6bc) scala> coll contains p res5: Boolean = true scala> p.x += 1 scala> coll contains p res7: Boolean = false scala> coll.elements contains p res8: Boolean = true scala> object Color extends Enumeration { val Red, Orange, Yellow, Green, Blue, Indigo, Violet = Value } defined module Color scala> class ColoredPoint(x: Int, y: Int, val color: Color.Value) extends Point(x, y) { // Problem: equals not symmetric override def equals(other: Any) = other match { case that: ColoredPoint => this.color == that.color && super.equals(that) case _ => false } } defined class ColoredPoint scala> val p = new Point(1, 2) p: Point = Point@6bc scala> val cp = new ColoredPoint(1, 2, Color.Red) cp: ColoredPoint = ColoredPoint@6bc scala> p equals cp res9: Boolean = true scala> cp equals p res10: Boolean = false scala> HashSet[Point](p) contains cp res11: Boolean = true scala> HashSet[Point](cp) contains p res12: Boolean = false scala> class ColoredPoint(x: Int, y: Int, val color: Color.Value) extends Point(x, y) { // Problem: equals not transitive override def equals(other: Any) = other match { case that: ColoredPoint => (this.color == that.color) && super.equals(that) case that: Point => that equals this case _ => false } } defined class ColoredPoint scala> val redp = new ColoredPoint(1, 2, Color.Red) redp: ColoredPoint = ColoredPoint@6bc scala> val bluep = new ColoredPoint(1, 2, Color.Blue) bluep: ColoredPoint = ColoredPoint@6bc scala> redp == p res13: Boolean = true scala> p == bluep res14: Boolean = true scala> redp == bluep res15: Boolean = false scala> // A technically valid, but unsatisfying, equals method class Point(val x: Int, val y: Int) { override def hashCode = 41 * (41 + x) + y override def equals(other: Any) = other match { case that: Point => this.x == that.x && this.y == that.y && this.getClass == that.getClass case _ => false } } defined class Point scala> class ColoredPoint(x: Int, y: Int, val color: Color.Value) extends Point(x, y) { override def equals(other: Any) = other match { case that: ColoredPoint => (this.color == that.color) && super.equals(that) case _ => false } } defined class ColoredPoint scala> val pAnon = new Point(1, 1) { override val y = 2 } pAnon: Point = $anon$1@6bc scala> class Point(val x: Int, val y: Int) { override def hashCode = 41 * (41 + x) + y override def equals(other: Any) = other match { case that: Point => (that canEqual this) && (this.x == that.x) && (this.y == that.y) case _ => false } def canEqual(other: Any) = other.isInstanceOf[Point] } defined class Point scala> class ColoredPoint(x: Int, y: Int, val color: Color.Value) extends Point(x, y) { override def hashCode = 41 * super.hashCode + color.hashCode override def equals(other: Any) = other match { case that: ColoredPoint => (that canEqual this) && super.equals(that) && this.color == that.color case _ => false } override def canEqual(other: Any) = other.isInstanceOf[ColoredPoint] } defined class ColoredPoint scala> val p = new Point(1, 2) p: Point = Point@6bc scala> val cp = new ColoredPoint(1, 2, Color.Indigo) cp: ColoredPoint = ColoredPoint@11421 scala> val pAnon = new Point(1, 1) { override val y = 2 } pAnon: Point = $anon$1@6bc scala> val coll = List(p) coll: List[Point] = List(Point@6bc) scala> coll contains p res16: Boolean = true scala> coll contains cp res17: Boolean = false scala> coll contains pAnon res18: Boolean = true scala> trait Tree[+T] { def elem: T def left: Tree[T] def right: Tree[T] } object EmptyTree extends Tree[Nothing] { def elem = throw new NoSuchElementException("EmptyTree.elem") def left = throw new NoSuchElementException("EmptyTree.left") def right = throw new NoSuchElementException("EmptyTree.right") } defined trait Tree defined module EmptyTree scala> class Branch[T]( val elem: T, val left: Tree[T], val right: Tree[T] ) extends Tree[T] { override def equals(other: Any) = other match { case that: Branch[T] => this.elem == that.elem && this.left == that.left && this.right == that.right case _ => false } } warning: there were unchecked warnings; re-run with -unchecked for details defined class Branch scala> val b1 = new Branch[List[String]](Nil, EmptyTree, EmptyTree) b1: Branch[List[String]] = Branch@eb691 scala> val b2 = new Branch[List[Int]](Nil, EmptyTree, EmptyTree) b2: Branch[List[Int]] = Branch@663187 scala> b1 == b2 res19: Boolean = true