будет неявно вызван метод to_int. Предположим, к примеру, что мы хотим создать массив с известным начальным числом элементов. Метод Array.new может принять целое, но что если вместо этого ему будет передан объект MyClass?

m = MyClass.new

a = Array.new(m) # [nil,nil,nil,nil,nil]

Как видите, метод new оказался достаточно «умным», чтобы вызвать to_int и затем создать массив из пяти элементов.

Дополнительную информацию о поведении в другом контексте (строковом) вы найдете в разделе 2.16. См. также раздел 5.16.

5.16. Приведение числовых значений

Приведение можно считать еще одним видом неявного преобразования. Если некоторому методу (например, +) передается аргумент, которого он не понимает, он пытается привести объект, от имени которого вызван, и аргумент к совместимым типам, а затем сложить их. Принцип использования метода coerce в вашем собственном классе понятен из следующего примера:

class MyNumberSystem

 def +(other)

  if other.kind_of?(MyNumberSystem)

   result = some_calculation_between_self_and_other

   MyNumberSystem.new(result)

  else

   n1, n2 = other.coerce(self)

   n1 + n2

  end

 end

end

Метод coerce возвращает массив из двух элементов, содержащий аргумент и вызывающий объект, приведенные к совместимым типам.

В данном примере мы полагаемся на то, что приведение выполнит тип аргумента. Но если мы хотим быть законопослушными гражданами, то должны реализовать приведение в своем классе, сделав его пригодным для работы с другими типами чисел. Для этого нужно знать, с какими типами мы в состоянии работать непосредственно, и при необходимости выполнять приведение к одному из этих типов. Если мы не можем сделать это самостоятельно, то должны обратиться за помощью к родительскому классу.

def coerce(other)

 if other.kind_of?(Float)

  return other, self.to_f

 elsif other.kind_of?(Integer)

  return other, self.to_i

 else

  super

 end

end

Разумеется, это будет работать только, если наш объект реализует методы to_i и to_f.

Метод coerce можно применить для реализации автоматического преобразования строк в числа, как в языке Perl:

class String

 def coerce(n)

  if self['.']

   [n, Float(self)]

  else

   [n, Integer(self)]

  end

 end

end

x = 1 + '23'    # 24

y = 23 * '1.23' # 28.29

Мы не настаиваем на таком решении. Но рекомендуем реализовывать coerce при создании любого класса для работы с числовыми данными.

5.17. Поразрядные операции над числами

Иногда требуется работать с двоичным представлением объекта Fixnum. На прикладном уровне такая необходимость возникает нечасто, но все-таки возникает.

Ruby обладает всеми средствами для таких операций. Для удобства числовые константы можно записывать в двоичном, восьмеричном или шестнадцатеричном виде. Поразрядным операциям И, ИЛИ, ИСКЛЮЧАЮЩЕЕ ИЛИ и НЕ соответствуют операторы &, |, ^ и ~.

x = 0377       # Восьмеричное (десятичное 255)

y = 0b00100110 # Двоичное (десятичное 38)

z = 0xBEEF     # Шестнадцатеричное (десятичное 48879)

а = x | z      # 48895 (поразрядное ИЛИ)

b = x & z      # 239 (поразрядное И)

с = x ^ z      # 48656 (поразрядное ИСКЛЮЧАЮЩЕЕ ИЛИ)

d = ~ y        # -39 (отрицание или дополнение до 1)

Метод экземпляра size позволяет узнать размер слова для той машины, на которой исполняется программа.

size # Для конкретной машины возвращает 4.

Имеются операторы сдвига влево и вправо (<< и >>соответственно). Это логические операторы сдвига, они не затрагивают знаковый бит (хотя оператор >> распространяет его).

x = 8

y = -8

а = x >> 2 # 2

b = y >> 2 # -2

с = x << 2 # 32

d = y << 2 # -32

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату