Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foo < Bar in Ruby

Tags:

ruby

I recently discovered that you can detect if a class/module includes another class/module. For example Array is Enumerable so you can do

Array < Enumerable # true

String however is not enumerable

String < Enumerable #nil

What exactly is happening here? How does this syntax work in ruby?

like image 493
Kyle Decot Avatar asked Jul 18 '13 17:07

Kyle Decot


3 Answers

Here is how to get the ancestor chain for a class:

>> Array.ancestors
=> [Array, Enumerable, Object, Kernel, BasicObject]

The < method returns true if a class is "left" of another class in the ancestor chain and false otherwise:

>> Array < Object
=> true
>> Array < Enumerable
=> true

The < method returns false if a class is not "left" or another class in the ancestor chain.

>> Enumerable < Array
=> false
>> Array < Array
=> false

Enumerable is a module that is mixed in in to the Array class, but not mixed in to the String class.

>> Array.ancestors
=> [Array, Enumerable, Object, Kernel, BasicObject]
>> String.ancestors
=> [String, Comparable, Object, Kernel, BasicObject]

If you include the Enumerable model into the String class, it returns true as well.

class String
  include Enumerable
end

# Enumerable is now included in String
String < Enumerable #true

The syntax works because of syntactic sugar. Everything is an object in Ruby and syntactic sugar is even used in basic operations like addition:

>> 3 + 4
=> 7
>> 3.+(4)
=> 7

The explicit syntax for the < method is as follows:

>> Array.<(Object)
=> true
>> Array.send(:<, Object)
=> true
like image 78
Powers Avatar answered Nov 19 '22 16:11

Powers


What exactly is happening here? How does this syntax work in ruby?

The String and Array classes inherit from the Class class which inherits from the Module class which defines the < class method as:

Returns true if the module is a subclass of the passed argument. Returns nil if there's no relationship between the two.

The syntax:

Array < Enumerable
String < Enumerable

can be seen as:

Array.< Enumerable
String.< Enumerable
like image 31
Shoe Avatar answered Nov 19 '22 14:11

Shoe


If the two modules appear in an ancestor chain, then the ordinary <=> applies with respect to their position in that chain. If not, nil is returned.

like image 3
sawa Avatar answered Nov 19 '22 14:11

sawa