Module: Yast2::Equatable

Defined in:
library/general/src/lib/yast2/equatable.rb

Overview

Mixin for classes that require to define a custom comparison

By default, the methods #==, #eql? and #equal? in Object subclasses return true if both objects are the same (point to the same object in memory). Actually #eql? should return true if both objects refer to the same hash key. But in practice, two objects have the same hash key if they are the very same object. There are some exceptions like String, which returns the same hash key if they have the same value.

The #eql? and #hash methods must be related. That is, if two objects are #eql?, then they should have the same #hash. This is important, otherwise we could have unexpected results in certain operations like subtracting Arrays. When performing the difference of two Arrays, the method used for comparing the objects in the Array depends on the Array length (see source code of Array#difference). If both Arrays have more than SMALL_ARRAY_LEN (i.e., 16) elements, then the #hash method is used. Otherwise it uses #eql?. This is one of the reason why #eql? and #hash should be paired.

Examples:

class Foo
  include Equatable

  attr_reader :attr1, :attr2

  eql_attr :attr1

  def initialize(attr1, attr2)
    @attr1 = attr1
    @attr2 = attr2
  end
end

foo1 = Foo.new("a", "b")
foo2 = Foo.new("a", "c")

foo1 == foo2      #=> true
foo1.eql?(foo2)   #=> true
foo1.equal?(foo2) #=> false

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#eql?(other) ⇒ Boolean Also known as: ==

Whether the objects have the same hash key

Parameters:

  • other (Object)

Returns:

  • (Boolean)


108
109
110
# File 'library/general/src/lib/yast2/equatable.rb', line 108

def eql?(other)
  hash == other.hash
end

#eql_hashHash<Symbol, Object]

Returns a Hash containing all the attributes and values used for comparing the objects as well as a :class key with the object class as the value.

Returns:

  • (Hash<Symbol, Object])

    Hash<Symbol, Object]



91
92
93
# File 'library/general/src/lib/yast2/equatable.rb', line 91

def eql_hash
  ([[:class, self.class]] + self.class.eql_attrs.map { |m| [m, send(m)] }).to_h
end

#hashInteger

Hash key to identify objects

Objects with the same values for their eql_attrs have the same hash

Returns:

  • (Integer)


100
101
102
# File 'library/general/src/lib/yast2/equatable.rb', line 100

def hash
  eql_hash.hash
end