Refinements war eine experimentelle Ergänzung zu v2.0, dann modifiziert und dauerhaft in v2.1 gemacht. Es bietet eine Möglichkeit, "Monkey-Patching" zu vermeiden, indem es "eine Möglichkeit bietet, eine Klasse lokal zu erweitern".Verwenden von Verfeinerungen hierarchisch
ich versuchte Refinements
-this recent question anzuwenden, die ich so vereinfacht:
a = [[1, "a"],
[2, "b"],
[3, "c"],
[4, "d"]]
b = [[1, "AA"],
[2, "B"],
[3, "C"],
[5, "D"]]
Das Element bei Offset i
in a
bei dem Element entspricht Offset i
in b
wenn:
a[i].first == b[i].first
und
a[i].last.downcase == b[i].last.downcase
Mit anderen Worten, die Übereinstimmung der Zeichenfolgen ist unabhängig von der Groß-/Kleinschreibung.
Das Problem besteht darin, die Anzahl der Elemente von a
zu ermitteln, die mit dem entsprechenden Element von b
übereinstimmen. Wir sehen, dass die Antwort zwei ist, die Elemente bei Offsets 1
und 2
.
Eine Möglichkeit, dies zu tun ist, um Affen-Patch String#==:
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
oder verwenden Sie stattdessen 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
Aber ich möchte Refinements
wie folgt verwenden:
using M
a.zip(b).count { |ae,be| ae == be }
#=> 0
aber, wie Sie sehen, das gibt die falsche Antwort. Das liegt daran, dass ich Array#== anrufe und die Verfeinerung nicht innerhalb von Array
gilt.
kann ich dies tun:
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
aber das ist nicht das, was ich will. Ich möchte so etwas tun:
module N
refine Array do
using M
end
end
using N
a.zip(b).count { |ae,be| ae == be }
#=> 0
aber klar, dass das nicht funktioniert.
Meine Frage: Gibt es eine Möglichkeit, String
zur Verwendung in Array
zu verfeinern, dann verfeinern Array
für die Verwendung in meiner Methode?
Das ist großartig! Ein Detail: Sie könnten erwägen, '! Self.zip (andere) .map {| x, y | zu ersetzen x == y} .einschließen? falsch 'mit' zip (andere) .alle? {| x, y | x == y} '. (Erinnern Sie sich, dass "Selbst" der Standardempfänger ist.) –
Ah, yeah, danke - Ich habe die schlechte Angewohnheit, 'self' zu verwenden, wo immer es angewendet werden könnte. Dies wird mir helfen, mich daran zu erinnern, ob es sinnvoll ist, es zu verwenden. Es sieht hier viel schöner/besser aus ohne "selbst" und "alle" zu benutzen. –
Viele Rubyisten benutzen 'self', wenn sie nicht gebraucht werden, weil sie glauben, dass ihre Auslassung für den Leser verwirrend sein könnte. Ich bin nicht in diesem Lager, aber ich kann nicht sagen, dass sie falsch liegen. –