6

メソッドにエイリアスを設定したい Ruby コードのセクションがあるとします (理由はわかりませんが、正当な理由があるとしましょう)。

class String
    alias_method :contains?, :include?
end

このセクションの後、このエイリアスを削除することはできますか?

4

2 に答える 2

7

remove_methodほとんどの場合に動作するはずです。ただし、既存のメソッドを上書きする場合は、別の呼び出しalias_methodで元のメソッドを保存する必要がある場合があります。alias_method

# assuming :contains? is already a method 
alias_method :original_contains?, :contains?
alias_method :contains?, :include?

次に、元の状態に戻すには:

alias_method :contains?, :original_contains?
remove_method :original_contains?  # optional

複数のスレッドで使用されるクラスを変更すると、競合状態が発生しやすいことにも注意してください。また、ライブラリがエイリアスを使用することを禁止しようとしている場合、エイリアスが存在するときにそれらのライブラリのメソッドを呼び出していると、それを防ぐことはできません。Ruby 2.0 でこれを行う方法が見られるかもしれません: http://yehudakatz.com/2010/11/30/ruby-2-0-refinements-in-practice/

エイリアスを削除したい理由を教えていただけると助かります。メソッド名が以前に存在しなかった場合、他のライブラリはモンキー パッチの影響を受けません。Stringまた、パッチを適用するのではなく、サブクラス化 (または文字列インスタンスへの委譲) を検討する必要がありますString

于 2012-07-12T17:41:24.503 に答える
4
def hello
   puts "Hello World"
end
alias :hi :hello

hi #=> "Hello World"
undef hi
hi #=> NameError
hello #=> "Hello World"

main編集:これは、オブジェクトで作成されたメソッドでのみ機能することに注意してください。これをクラスで実行するには、次のようにする必要があります。Hello.class_eval("undef hi")

ただし、メタプログラミングの観点からは、クラスを扱う場合remove_method :hi、メソッド ルックアップが失敗し、親クラスからメソッドを取得する原因となるため、 の使用法が気に入っています。

class Nums < Array
   def include?
      puts "Just Kidding"
   end
end

n = Nums.new
n << 4 #=> [4]
n.include? #=> "Just kidding"
Nums.class_eval("remove_method :include?")
n.include? 4 #=> true
Number.class_eval("undef include?")
n.include? 4 #=> NoMethodError

remove_methodはるかにメタフレンドリーです。

于 2012-07-12T17:26:34.113 に答える