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 Equality
s, 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
Double
s 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
- Alphabetic
- By Inheritance
- Equivalence
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Abstract Value Members
-
abstract
def
areEquivalent(a: T, b: T): Boolean
Indicates whether the objects passed as
a
andb
are equal.Indicates whether the objects passed as
a
andb
are equal.Note: this
areEquivalent
method means essentially the same thing as theareEqual
method of traitEquality
, the difference only being the static type of the right-hand value. This method is namedareEquivalent
instead ofareEqual
so that it can be implemented in terms ofareEqual
in traitEquality
(which extendsEquivalence
).- 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
-
final
def
!=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
##(): Int
- Definition Classes
- AnyRef → Any
-
final
def
==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
asInstanceOf[T0]: T0
- Definition Classes
- Any
-
def
clone(): AnyRef
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @native() @throws( ... )
-
final
def
eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
def
equals(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
finalize(): Unit
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( classOf[java.lang.Throwable] )
-
final
def
getClass(): Class[_]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
def
hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
final
def
isInstanceOf[T0]: Boolean
- Definition Classes
- Any
-
final
def
ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
final
def
notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
final
def
notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
final
def
synchronized[T0](arg0: ⇒ T0): T0
- Definition Classes
- AnyRef
-
def
toString(): String
- Definition Classes
- AnyRef → Any
-
final
def
wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @native() @throws( ... )