Indicates whether the objects passed as a
and b
are equal.
Indicates whether the objects passed as a
and b
are equal.
a left-hand value being compared with another (right-hand-side one) for equality (e.g., a == b
)
a right-hand value being compared with another (left-hand-side one) for equality (e.g., a == b
)
true if the passed objects are "equal," as defined by this Equality
instance
A final implementation of the areEquivalent
method of Equivalence
that just passes
a
and b
to areEqual
and returns the result.
A final implementation of the areEquivalent
method of Equivalence
that just passes
a
and b
to areEqual
and returns the result.
This method enables any Equality
to be used where an Equivalence
is needed, such
as the implicit enabling methods of TypeCheckedTripleEquals
and ConversionCheckedTripleEquals
.
a left-hand value being compared with another, right-hand, value for equality (e.g., a == b
)
a right-hand value being compared with another, left-hand, value for equality (e.g., a == b
)
true if the passed objects are "equal," as defined by the areEqual
method of this
Equality
instance
Defines a custom way to determine equality for a type when compared with another value of type
Any
.Equality
enables you to define alternate notions of equality for types that can be used with ScalaUtil's===
and!==
syntax and ScalaTest's matcher syntax.For example, say you have a case class that includes a
Double
value: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:The
===
operator looks for an implicitEquality[L]
, whereL
is the left-hand type: in this case,Person
. Because you didn't specifically provide an implicitEquality[Person]
,===
will fall back on default equality, which will callPerson
'sequals
method. Thatequals
method, provided by the Scala compiler becausePerson
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
Equality[Person]
that compares theage
Double
s with a tolerance, like this:Now the
===
operator will use your more forgivingEquality[Person]
for the equality check instead of default equality:Default equality
ScalaUtils defines a default
Equality[T]
for all typesT
whoseareEqual
method works by first calling.deep
on any passed array, then calling==
on the left-hand object, passing in the right-hand object. You can obtain a default equality via thedefault
method of the Equality companion object, or from thedefaultEquality
method defined inTripleEqualsSupport
.About equality and equivalence
The
Equality
trait represents the Java Platform's native notion of equality, as expressed in the signature and contract of theequals
method ofjava.lang.Object
. Essentially, traitEquality
enables you to write alternateequals
method implementations for a type outside its defining class.In an
equals
method, the left-hand type is known to be the type ofthis
, but the right-hand type isAny
. As a result, you would normally perform a runtime type test to determine whether the right-hand object is of an appropriate type for equality, and if so, compare it structurally for equality with the left-hand (this
) object. An an illustration, here's a possibleequals
implementation for thePerson
case class shown in the earlier example:The
areEquals
method ofEquality[T]
is similar. The left-hand type is known to beT
, but the right-hand type isAny
, so normally you'd need to do a runtime type test in yourareEqual
implementation. Here's theareEqual
method implementation from the earlierEquality[Person]
example:Equality
is used byTripleEquals
, which enforces no type constraint between the left and right values, and theequal
,be
, andcontain
syntax of ScalaTest Matchers.By contrast,
TypeCheckedTripleEquals
andConversionCheckedTripleEquals
use anEquivalence
.Equivalence
differs fromEquality
in that both the left and right values are of the same type.Equivalence
works forTypeCheckedTripleEquals
because the type constraint enforces that the left type is a subtype or supertype of (or the same type as) the right type, and it widens the subtype to the supertype. So ultimately, both left and right sides are of the supertype type. Similarly,Equivalence
works forConversionCheckedTripleEquals
because the type constraint enforces that an implicit conversion exists from either the left type to the right type, or the right type to the left type, and it always converts one type to the other using the implicit conversion. (If both types are the same type, the identity implicit conversion fromPredef
is used.) Because of the conversion, both left and right sides are ultimately of the converted-to type. Here's an example of how writing anEquivalence
'sareEquivalent
method might look:ScalaUtils provides both
Equality
andEquivalence
because theAny
inEquality
can sometimes make things painful. For example, in traitTolerantNumerics
, a single generic factory method can produceEquivalence
s for anyNumeric
type, but because of theAny
, a separate factory method must be defined to produce anEquality
for eachNumeric
type.If you just want to customize the notion of equality for
===
used inBoolean
expressions, you can work withEquivalence
s instead ofEquality
s. If you do chose to write the more generalEquality
s, they can be used wherever anEquivalence
is required, becauseEquality
extendsEquivalence
, defining a final implementation ofareEquivalent
that invokesareEqual
.Note: The
Equality
type class was inspired in part by theEqual
type class of thescalaz
project.the type whose equality is being customized