With value classes in scala, ==
and !=
do value check.
Value classes are classes whose instances are not represented as
objects by the underlying host system. All value classes inherit from
class AnyVal.
all primitives in scala Int
, Float
etc are value classes.
scala> val quantity1 = 100
quantity1: Int = 100
scala> val quantity2 = 100
quantity2: Int = 100
scala> quantity1 == quantity2
res9: Boolean = true
Also, with case classes
, ==
works implicitily.,
Case classes are plain and immutable data-holding objects that should
exclusively depend on their constructor arguments
scala> case class Item(name: String, quantity: Int)
defined class Item
Now, compare two items just by ==
will check if all the values in item are equal.
scala> Item("Jacket", 100) == Item("Pants", 10)
res0: Boolean = false
scala> Item("Jacket", 100) == Item("Jacket", 100)
res1: Boolean = true
Case 2 - Ref classes in scala(AnyRef
) and java classes(java.lang.Object
)
But with Ref
classes in scala and all Java classes, if you do ==
, it checks the instance reference instead of values until you write your own equals method.
Java Example,
static class Item {
String name;
int quantity;
Item(String name, int quantity){
this.name = name;
this.quantity = quantity;
}
}
public static void main(String[] args) {
Item item1 = new Item("Jacket", 100);
Item item2 = new Item("Pants", 10);
Item item3 = new Item("Jacket", 100);
System.out.println(item1 +"==" + item2 + " " + (item1 == item2)); //false
System.out.println(item1 +"==" + item3 + " " + (item1 == item3)); //false
}
the ==
comparison result would be
com.somepackage.EqualityTests$Item@1b28cdfa==com.somepackage.EqualityTests$Item@eed1f14 false
com.somepackage.EqualityTests$Item@1b28cdfa==com.somepackage.EqualityTests$Item@7229724f false
Where 1b28cdfa
is the instance ref for item1
. You see item1
and item3
have same data but ==
gives false because they are two different instances referring to two different addresses.
To mimick what scala does on value class ==
, implement your equals
method as below and do manual equality check.
static class Item {
String name;
int quantity;
Item(String name, int quantity){
this.name = name;
this.quantity = quantity;
}
@Override
public boolean equals(Object obj) {
Item i = (Item) obj;
return this.name.equals(((Item) obj).name) && this.quantity == ((Item) obj).quantity;
}
}
public static void main(String[] args) {
Item item1 = new Item("Jacket", 100);
Item item2 = new Item("Pants", 10);
Item item3 = new Item("Jacket", 100);
System.out.println(item1 +".equals(" + item3 + ") " + (item1.equals(item3))); //true
}
Same with scala Ref classes, that `==` compares the reference if equals method is not implemented
scala> class Store(name: String){} //equivalent to Store extends `AnyRef`
defined class Store
scala> val store1 = new Store("a")
store1: Store = Store@2063c53e
scala> val store2 = new Store("a")
store2: Store = Store@61c76850
scala> store1 == store2
res7: Boolean = false
But if there's your own equals
method in scala Ref classes then == refers to your .equals
method.
Example,
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Store(val name: String){
override def equals(that: Any) : Boolean = {
val thatStore = that.asInstanceOf[Store]
name == thatStore.name
}
}
scala> new Store("JWN") == new Store("JWN") // calls s1.equals(s2)
res1: Boolean = true