2.18.  Objects comparison

[Warning]Text not verified for kermeta 2

Kermeta users could be confused about == operator and equals method. Unlike, Java they do the same and redefining the equals to compare the content also affects the == .

To compare the identity of two objects you must compare the identifier of each object : using their oid

2.18.1. equals method

The equals method behaves the same way as in java. This means that you can overwrite it, if you want to compare the contents of two objects of the same class.

@mainClass "root::Main"
@mainOperation "main"

package root;

require kermeta
using kermeta::standard
using kermeta::kunit
class A {

  reference x : Integer

  method equals(compared : Object) : Boolean is do
    var castedCompared : A
    castedCompared ?= compared
    result := x.equals (castedCompared.x)
  end

}


class Main inherits kermeta::kunit::TestCase{

  operation main() : Void is do

    var a1 : A init A.new
    var a2 : A init A.new
 
    a1.x := 10
    a2.x := 20

    assert( not a1.equals(a2) )	// objects are different with all methods
    assert( not a1 == a2 )
    assert ( a1.oid == a2.oid ) 

    a2.x := 10
 
    assert ( a1.equals(a2) ) 	// objects becomes equals
    assert ( a1 == a2  )		// also with ==
    assert ( a1.oid == a2.oid ) // but they physically are still different

  end

}

2.18.2. Comparison for Primitive Types

In Kermeta language, there is a notion of primitive type. Here is the list of primitive types :

  • Boolean

  • Integer

  • String

  • Character

  • Real

We do not want two Integer objects with the same value to be different. What we want is to use == operator to compare values of primitive types. These classes simply redefine the equals. Then we can write this code :

var i1 : Integer init 10
var i2 : Integer init 10
assert (i1.equals(i2))

var i3 : Integer init 10
var i4 : Integer init 10
assert (i3 == i4)

2.18.3. Collection comparison

The method equals exists for the collections. The generic behavior is the following : for two collections a and b, if all elements of a are contained in b and vice-versa, then it returns true, false otherwise. This behavior is little bit different for ordered collection which takes into account the order of elements. Have a look to the following pieces of code :

operation test_try1() : Void is do
   var os : OrderedSet<Integer> init OrderedSet<Integer>.new
   os.add(1) os.add(2) os.add(3) os.add(4) os.add(5) os.add(6)

   var os2 : OrderedSet<Integer> init OrderedSet<Integer>.new
   os2.add(1) os2.add(2) os2.add(3) os2.add(4) os2.add(5) os2.add(6)

   assert (os.equals(os2) )
end

operation test_try2() : Void is do
   var os : OrderedSet<Integer> init OrderedSet<Integer>.new
   os.add(1) os.add(2) os.add(3) os.add(4) os.add(5) os.add(6)

   var os2 : OrderedSet<Integer> init OrderedSet<Integer>.new
   os2.add(1) os2.add(2) os2.add(3) os2.add(4) os2.add(5)

   assert ( not os.equals(os2) )
end

/**
 * An ordered set takes care about the order.
 */
operation test_try3() : Void is do
   var os : OrderedSet<Integer> init OrderedSet<Integer>.new
   os.add(1) os.add(2) os.add(3) os.add(4) os.add(5) os.add(6)

   var os2 : OrderedSet<Integer> init OrderedSet<Integer>.new
   os2.add(4) os2.add(6) os2.add(3) os2.add(1) os2.add(5) os2.add(2)

   assert ( not os.equals(os2) )
end

/**
 * A set does not care about the order.
 */
operation test_try4() : Void is do
   var os : Set<Integer> init Set<Integer>.new
   os.add(1) os.add(2) os.add(3) os.add(4) os.add(5) os.add(6)

   var os2 : Set<Integer> init Set<Integer>.new
   os2.add(4) os2.add(6) os2.add(3) os2.add(1) os2.add(5) os2.add(2)

   assert ( os.equals(os2) )
end