Уточнения были экспериментальным дополнением к версии 2.0, затем изменен и сделан постоянным в v2.1. Он дает возможность избежать «обезьяньих исправлений», предоставляя «способ локального расширения класса».
Я попытался применить Refinements
к этому недавнему вопросу, который я упрощу таким образом:
a = [[1, "a"],
[2, "b"],
[3, "c"],
[4, "d"]]
b = [[1, "AA"],
[2, "B"],
[3, "C"],
[5, "D"]]
Элемент со смещением i
в a
соответствует элементу со смещением i
в b
, если:
a[i].first == b[i].first
а также
a[i].last.downcase == b[i].last.downcase
Другими словами, соответствие строк не зависит от регистра.
Проблема состоит в том, чтобы определить количество элементов a
, которые соответствуют соответствующему элементу b
. Мы видим, что ответов два, элементы со смещениями 1
и 2
.
Один из способов сделать это — выполнить обезьянью исправление Строка#==:
class String
alias :dbl_eql :==
def ==(other)
downcase.dbl_eql(other.downcase)
end
end
a.zip(b).count { |ae,be| ae.zip(be).all? { |aee,bee| aee==bee } }
#=> 2
или вместо этого используйте Refinements
:
module M
refine String do
alias :dbl_eql :==
def ==(other)
downcase.dbl_eql(other.downcase)
end
end
end
'a' == 'A'
#=> false (as expected)
a.zip(b).count { |ae,be| ae.zip(be).all? { |aee,bee| aee==bee } }
#=> 0 (as expected)
using M
'a' == 'A'
#=> true
a.zip(b).count { |ae,be| ae.zip(be).all? { |aee,bee| aee==bee } }
#=> 2
Однако я хотел бы использовать Refinements
вот так:
using M
a.zip(b).count { |ae,be| ae == be }
#=> 0
но, как видите, это дает неверный ответ. Это потому, что я вызываю Array#== и уточнение не применяется в пределах Array
.
Я мог бы сделать это:
module N
refine Array do
def ==(other)
zip(other).all? do |ae,be|
case ae
when String
ae.downcase==be.downcase
else
ae==be
end
end
end
end
end
using N
a.zip(b).count { |ae,be| ae == be }
#=> 2
но это не то, что я хочу. Я хочу сделать что-то вроде этого:
module N
refine Array do
using M
end
end
using N
a.zip(b).count { |ae,be| ae == be }
#=> 0
но ясно, что это не работает.
Мой вопрос: есть ли способ уточнить String
для использования в Array
, а затем уточнить Array
для использования в моем методе?