質問
まだまだ新しいRuby-コンテンツビジネスだけでは基本的に書き初めてのマイクロプログラム後の仕上げクーパーイメージが生まれました。私はこの方向を回避するサルパッチングが、問題はどうなるかはわからないの選択肢を同じ行動です。基本的に付け加えておきたい新しい方法でもアクセス可能な各stringオブジェクトです。を明らかなモンキ-パッチング方法は:
class String
def do_magic
...magic...
end
end
思い出があり方を文字列になります。への送信時だけ有効です。がどうかよろしくお願いしますどうな場いただいていました。誰でもできるので行代わるも作らせて頂いています。る方法、文字列のクラスの子オブジェ?
解決
これを行うための他の方法は、ちょうど猿のパッチ適用のためのより厄介な構文になります。そこsend
とeval
とあらゆる種類のものを含む方法がありますが、の理由の?先に行くと、それを明白な方法を行います。
あなたは大きなプロジェクトで猿のパッチ適用を慎重になりたいか、あなたが依存関係を持っている場合、いくつかの手はすべて同じ場所にいじりされている場合、あなたは競合に巻くことができるので。これは、同じことを達成代替構文を探すという意味ではありません - それはあなたがあなたではないのコードに影響を与える可能性の変更を行っているときに注意する必要があることを意味します。これはおそらく、あなたの特定のケースでは問題になりません。それはちょうど、大規模なプロジェクトに対処する必要があるかもしれません何かます。
Rubyで1つの選択肢は、あなたが単一のオブジェクトにメソッドを追加できることです。
a = "Hello"
b = "Goodbye"
class <<a
def to_slang
"yo"
end
end
a.to_slang # => "yo"
b.to_slang # NoMethodError: undefined method `to_slang' for "Goodbye":String
他のヒント
、それを行うと、あなたはそれを持っている方法は、それを成し遂げる方法です。
良い習慣は、(string_ex.rb
またはextensions
など)(core_ext
のような)別のファイルやサブディレクトリ内のコアオブジェクトへの拡張機能を置くことです。拡張されたもの。この方法は、それは明らかである、と誰かが、彼らは拡張または変更されたかを確認することが容易です。
あなたは、元の機能は、不正な動作を期待し、いくつかの他のコードを引き起こしコアオブジェクトのいくつかの既存の動作を変更する際に猿のパッチ適用が悪いされて行くことができます。
の object
クラス定義 send
, は、すべてのオブジェクトを継承します。い"送信"オブジェクトの send
方法。の send
メソッドのパラメータの方法-ご-たい-に-を呼び出す名シンボルとして、その後の引数およびオプションのブロックです。も利用できます __send__
.
>> "heya".send :reverse
=> "ayeh"
>> space = %w( moon star sun galaxy )
>> space.send(:collect) { |el| el.send :upcase! }
=> ["MOON", "STAR", "SUN", "GALAXY"]
編集..
ほとんどの場合にご使用になりたい define_method
方法:
String.class_eval {
define_method :hello do |name|
self.gsub(/(\w+)/,'hello') + " #{name}"
end
}
puts "Once upon a time".hello("Dylan")
# >> hello hello hello hello Dylan
このインスタンスに追加します。追加クラスメソッド:
eigenclass = class << String; self; end
eigenclass.class_eval {
define_method :hello do
"hello"
end
}
puts String.hello
# >> hello
できませんの定義方法とブロックになってる。
ですが、良い読み取りの この章からなぜワードガイド, き飛ばしになっている必要がありDwemthyの配列"をメタプログラミング。
みんなありがとうます。
提案、実装作業のすべて。さらに重要なことは、私が手にした場合に計量し、再オープンコア(またはライブラリ)のクラスは良いアイデアであるかどうかを決定することを学んだ。
FWIW、友人は私が探していたsend
実装を指摘しました。しかし、今、私はそれを見ていること、それはすべての他の実装よりもmonkeypatchingにさらに近いです:)
module M
def do_magic
....
end
end
String.send(:include, M)
クラスやオブジェクトに機能を付加する代わりに、あなたは常に機能的なルートを行くことができます:
class StringMagic
def self.do(string)
...
end
end
StringMagic.do("I'm a String.") # => "I'm a MAGIC String!"
「モンキーパッチ」あなたが(例えば、宝石のような)他の誰かがあなたのコードを必要としたい場合は確かに問題になる可能性について説明します。彼らはまた、do_magic呼ばれる文字列のメソッドを追加したくないだろうと言って誰ですか?一つの方法は、他に上書きされますが、これはデバッグに挑戦することができます。あなたのコードがオープンソースになります任意のチャンスがあれば、それは独自のクラスを作成することをお勧めします:
class MyString < String
def initialize(str)
@str = str
end
def do_magic
...magic done on @str
@str
end
end
さて、あなたはあなたをdo_magicする必要がある場合することができます。
magic_str = MyString.new(str).do_magic