org.scalactic

Equivalence

trait Equivalence[T] extends AnyRef

Defines a custom way to determine equality for a type when compared with another value of the same type.

Equivalence enables you to define alternate notions of equality for types that can be used with ScalaUtil's TypeCheckedTripleEquals and ConversionCheckedTripleEquals traits. These traits can be used to perform equality comparisons with type constraints enforced at compile time using ScalaUtil's === and !== syntax and ScalaTest's should === syntax of Matchers trait.

Because Equality extends Equivalence, you automatically define an Equivalence[T] when you define an Equality[T]. Most often you will usually want to define custom Equalitys, because they will be more generally useful: they are also used by Scalactic's TripleEquals trait and ScalaTest's equal, be, and contain matcher syntax. However, if you really want just an Equivalence, and writing an Equality is inconvenient, you can write an Equivalence directly for a type.

For example, say you have a case class that includes a Double value:

scala> case class Person(name: String, age: Double)
defined class Person

Imagine you are calculating the age values in such as way that occasionally tests are failing because of rounding differences that you actually don't care about. For example, you expect an age of 29.0, but you're sometimes seeing 29.0001:

scala> import org.scalactic._
import org.scalactic._

scala> import TypeCheckedTripleEquals._
import TypeCheckedTripleEquals._

scala> Person("Joe", 29.0001) === Person("Joe", 29.0)
res0: Boolean = false

The === operator of TypeCheckedTripleEquals looks for an implicit Equivalence[SUPER], where SUPER is either the left-hand or right-hand type, whichever one is a supertype of the other. In this case, both sides are Person (which is considered a supertype of itself), so the compiler will look for an Equivalence[Person]. Because you didn't specifically provide an implicit Equivalence[Person], === will fall back on default equality, because an Equality[Person] is-an Equivalence[Person]. The default Equality[Person] will call Person's equals method. That equals method, provided by the Scala compiler because Person is a case class, will declare these two objects unequal because 29.001 does not exactly equal 29.0.

To make the equality check more forgiving, you could define an implicit Equivalence[Person] that compares the age Doubles with a tolerance, like this:

scala> import Tolerance._
import Tolerance._

scala> implicit val personEq =
     |   new Equivalence[Person] {
     |     def areEquivalent(a: Person, b: Person): Boolean =
     |       a.name == b.name && a.age === b.age +- 0.0002
     |   }
personEq: org.scalactic.Equivalence[Person] = $anon$1@7892bd8

Now the === operator will use your more forgiving Equivalence[Person] for the equality check instead of default equality:

scala> Person("Joe", 29.0001) === Person("Joe", 29.0)
res1: Boolean = true

Source
Equivalence.scala
Linear Supertypes
AnyRef, Any
Known Subclasses
Ordering
  1. Alphabetic
  2. By inheritance
Inherited
  1. Equivalence
  2. AnyRef
  3. Any
  1. Hide All
  2. Show all
Learn more about member selection
Visibility
  1. Public
  2. All

Abstract Value Members

  1. abstract def areEquivalent(a: T, b: T): Boolean

    Indicates whether the objects passed as a and b are equal.

    Indicates whether the objects passed as a and b are equal.

    Note: this areEquivalent method means essentially the same thing as the areEqual method of trait Equality, the difference only being the static type of the right-hand value. This method is named areEquivalent instead of areEqual so that it can be implemented in terms of areEqual in trait Equality (which extends Equivalence).

    a

    a left-hand-side object being compared with another (right-hand-side one) for equality (e.g., a == b)

    b

    a right-hand-side object being compared with another (left-hand-side one) for equality (e.g., a == b)

    returns

    true if the passed objects are "equal," as defined by this Equivalence instance

Concrete Value Members

  1. final def !=(arg0: Any): Boolean

    Definition Classes
    AnyRef → Any
  2. final def ##(): Int

    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean

    Definition Classes
    AnyRef → Any
  4. final def asInstanceOf[T0]: T0

    Definition Classes
    Any
  5. def clone(): AnyRef

    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  6. final def eq(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  7. def equals(arg0: Any): Boolean

    Definition Classes
    AnyRef → Any
  8. def finalize(): Unit

    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  9. final def getClass(): Class[_]

    Definition Classes
    AnyRef → Any
  10. def hashCode(): Int

    Definition Classes
    AnyRef → Any
  11. final def isInstanceOf[T0]: Boolean

    Definition Classes
    Any
  12. final def ne(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  13. final def notify(): Unit

    Definition Classes
    AnyRef
  14. final def notifyAll(): Unit

    Definition Classes
    AnyRef
  15. final def synchronized[T0](arg0: ⇒ T0): T0

    Definition Classes
    AnyRef
  16. def toString(): String

    Definition Classes
    AnyRef → Any
  17. final def wait(): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  18. final def wait(arg0: Long, arg1: Int): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  19. final def wait(arg0: Long): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws( ... )

Inherited from AnyRef

Inherited from Any

Ungrouped