-3

I am learning scala and going over the fundamentals.

I couldn't understand what it means by "In Scala == and != methods check for value equaliy as opposed to Java where they check reference equality".

can someone give some example and try to explain in plain english?

jason
  • 65
  • 7

1 Answers1

2

Case 1 - value classes(AnyVal) and case classes

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
Community
  • 1
  • 1
prayagupa
  • 30,204
  • 14
  • 155
  • 192
  • Both "in scala, == and != do value check" and "But in Java, if you do ==, it checks the instance reference instead of values until you write your own equals method" are wrong (first is sometimes, second is always). – Alexey Romanov Mar 17 '17 at 20:26
  • @AlexeyRomanov thats right, it depends whether the object I create is value class or ref class in scala. – prayagupa Mar 17 '17 at 21:00
  • you are right. my answer had type on case class example, which does not need to extend `AnyVal`. – prayagupa Mar 18 '17 at 00:01
  • case class Store(name:String, zipcode:String) Store("AlamedaTarge", "94501") == Store("AlamedaTarge","94501") – jason Mar 18 '17 at 01:07
  • I dont know what you are saying. `Store("AlamedaTarge", "94501") == Store("AlamedaTarge","94501")` should be true, as `Store` is a case class. but if you make it `AnyRef` then to access the params declare them as `val` and override equals method. Example. `class Store(val name:String, val zipcode:String) extends AnyRef {}` – prayagupa Mar 18 '17 at 01:54