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.Equalityenables 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
Doublevalue:Imagine you are calculating the
agevalues 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], whereLis 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'sequalsmethod. Thatequalsmethod, provided by the Scala compiler becausePersonis 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 theageDoubles with a tolerance, like this:Now the
===operator will use your more forgivingEquality[Person]for the equality check instead of default equality:scala> Person("Joe", 29.0001) === Person("Joe", 29.0) res1: Boolean = trueDefault equality
Scalactic defines a default
Equality[T]for all typesTwhoseareEqualmethod works by first calling.deepon any passed array, then calling==on the left-hand object, passing in the right-hand object. You can obtain a default equality via thedefaultmethod of the Equality companion object, or from thedefaultEqualitymethod defined inTripleEqualsSupport.About equality and equivalence
The
Equalitytrait represents the Java Platform's native notion of equality, as expressed in the signature and contract of theequalsmethod ofjava.lang.Object. Essentially, traitEqualityenables you to write alternateequalsmethod implementations for a type outside its defining class.In an
equalsmethod, 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 possibleequalsimplementation for thePersoncase class shown in the earlier example:The
areEqualsmethod 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 yourareEqualimplementation. Here's theareEqualmethod implementation from the earlierEquality[Person]example:Equalityis used byTripleEquals, which enforces no type constraint between the left and right values, and theequal,be, andcontainsyntax of ScalaTest Matchers.By contrast,
TypeCheckedTripleEqualsandConversionCheckedTripleEqualsuse anEquivalence.Equivalencediffers fromEqualityin that both the left and right values are of the same type.Equivalenceworks forTypeCheckedTripleEqualsbecause 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,Equivalenceworks forConversionCheckedTripleEqualsbecause 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 fromPredefis 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'sareEquivalentmethod might look:Scalactic provides both
EqualityandEquivalencebecause theAnyinEqualitycan sometimes make things painful. For example, in traitTolerantNumerics, a single generic factory method can produceEquivalences for anyNumerictype, but because of theAny, a separate factory method must be defined to produce anEqualityfor eachNumerictype.If you just want to customize the notion of equality for
===used inBooleanexpressions, you can work withEquivalences instead ofEqualitys. If you do chose to write the more generalEqualitys, they can be used wherever anEquivalenceis required, becauseEqualityextendsEquivalence, defining a final implementation ofareEquivalentthat invokesareEqual.Note: The
Equalitytype class was inspired in part by theEqualtype class of thescalazproject.the type whose equality is being customized