diff options
Diffstat (limited to 'src/library/scala/util/Hashable.scala')
-rw-r--r-- | src/library/scala/util/Hashable.scala | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/library/scala/util/Hashable.scala b/src/library/scala/util/Hashable.scala new file mode 100644 index 0000000000..88d3b72fbd --- /dev/null +++ b/src/library/scala/util/Hashable.scala @@ -0,0 +1,55 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.util + +/** A convenience trait for simplifying hashCode creation. + * Mix this into a class and define val hashValues = List(x1, x2, ...) + * and your hashCode will be derived from those values. If you define + * equals in terms of equalHashValues then your hashCode and equals + * methods will never be out of sync. Something like: + * + * override def equals(other: Any) = other match { + * case x: YourClass => this equalHashValues x + * case _ => false + * } + * + * @author Paul Phillips + */ +abstract trait Hashable extends AnyRef +{ + import Hashable._ + protected def hashValues: List[Any] // in an ideal universe this would be more like List[Hashable] + protected def hashSeed: Int = 0 + + override def hashCode: Int = + (hashValues map calculateHashCode).foldLeft(hashSeed)((x, y) => x * 41 + y) + + protected def equalHashValues(other: Any) = other match { + case x: Hashable => hashValues == x.hashValues + case _ => false + } +} +abstract trait StrictHashable extends Hashable +{ + protected def hashValues: List[Hashable] +} + +object Hashable +{ + /** This implicit is for StrictHashable's benefit, so your hashValues list + * can contain both explicitly Hashable classes and value types. + */ + implicit def anyVal2Hashable(x: AnyVal): Hashable = + new Hashable { protected def hashValues = List(x) } + + private def calculateHashCode(x: Any) = x match { + case null => 0 + case x: AnyRef => x.hashCode + case x => x.asInstanceOf[AnyRef].hashCode + } +}
\ No newline at end of file |