У меня есть класс, который использует Enumerable
и Forwardable
mixins. Дело в том, что хотя #each
был реализован (или делегирован), #member?
(который также поставляется с Enumerable
) работает неправильно.Ruby Перечисляемый с помощью Hash
require "forwardable"
class RestrictedHash
include Enumerable
extend Forwardable
def_delegators :@hash, :[], :[]=, :each
def initialize
@hash = {}
end
end
r_h = RestrictedHash.new
r_h[:a] = []
r_h.member?(:a) #=> false
r_h.member?(:a, []) #=> Wrong number of arguments (2 for 1)
r_h.member?([:a, []]) #=> true
h = {}
h[:a] = []
h.member?(:a) #=> true
h.member?([:a, []]) #=> false
Любые идеи, почему я получаю эту разницу в поведении?
Так что, хотя хэши реализуют «интерфейс» Перечислимый, он фактически реализует методы, а не просто включает Enumerable? – cenouro
Я не уверен в деталях этого. Короткий ответ заключается в том, что с помощью MRI (эталонная реализация Ruby) 'Hash' реализуется в C, а не как Ruby-код, и все методы из' Enumerable' имеют реализации C в источнике, с которым я связан. Если вы проверите этот код на GitHub, вы также увидите строку 'rb_include_module (rb_cHash, rb_mEnumerable)' теперь я не уверен, добавляет ли она какую-либо реализацию или просто вызывает перечисление «Enumerable» в 'Hash.ancestors', поэтому что 'Hash' можно рассматривать как класс, который включает' Enumerable'. Извините, это еще не окончательно! – mikej
Я сделал сценарий для анализа того, какие методы были переопределены или нет. Оказывается, у Hash есть много методов из 'Enumerable', но он переопределяет некоторые методы, содержащиеся в' Enumerable'. Сценарий таков: 'Enumerable.instance_methods.each {| method | puts "# {method} # {Hash.new.method (method.to_sym) .owner}"} ' – cenouro