web-dev-qa-db-ja.com

クラスメソッドの削除/未定義

次のように、クラスのクラスメソッドを動的に定義できます。

class Foo
end

bar = %q{def bar() "bar!" end}
Foo.instance_eval(bar)

しかし、どのように反対を行いますか:remove/undefineクラスメソッド?モジュールのremove_methodおよびundef_methodメソッドがこの目的に使用できると思われますが、何時間もGooglingした後に見たすべての例は、削除/定義解除のためのものでした。 )instanceメソッド。クラスメソッドではありません。あるいは、instance_evalに渡してこれを行うための構文があるかもしれません。

前もって感謝します。

51
Brian Ploetz
#!/usr/bin/Ruby1.8

class Foo

  def Foo.bar
    puts "bar"
  end

end

Foo.bar    # => bar

class <<Foo
  remove_method :bar
end

Foo.bar    # => undefined method `bar' for Foo:Class (NoMethodError)

Foo.barのようなクラスメソッドを定義すると、RubyによってFooの固有クラスになります。 Rubyはインスタンスメソッドになるため、Fooに配置できません。 Rubyは、Fooの固有クラス(別名「シングルトンクラス」)を作成し、固有クラスのスーパークラスをFooのスーパークラスに設定してから、Fooのスーパークラスを固有クラスに設定します。

Foo -------------> Foo(eigenclass) -------------> Object
        super      def bar             super

そのため、メソッドバーを削除するには、class <<Fooを使用してFooの固有クラスを開く必要があります。

63
Wayne Conrad

これは私にとっても機能します(undefとremove_methodの間に違いがあるかどうかはわかりません):

class Foo
end

Foo.instance_eval do
  def color
    "green"
  end
end

Foo.color # => "green"

Foo.instance_eval { undef :color }

Foo.color # => NoMethodError: undefined method `color' for Foo:Class
18
Adrian Macneil

私は十分な信用がないので、エイドリアンの答えについてコメントすることはできないと思うが、彼の答えは私を助けた。

私が見つけたもの:undefはメソッドを完全に削除しているようですが、remove_methodはそのクラスから削除しますが、スーパークラスまたはこのクラスで拡張された他のモジュールなどで定義されます。

6
Jeff Gran

メソッドは2つの簡単な方法で削除できます。抜本的な

Module#undef_method( ) 

継承されたものを含むすべてのメソッドを削除します。キンダー

Module#remove_method( ) 

レシーバからメソッドを削除しますが、継承されたメソッドはそのままにします。

以下の2つの簡単な例を参照してください-

undef_methodを使用した例1

class A 
    def x
        puts "x from A class"
    end
end

class B < A
    def x
        puts "x from B Class"
    end
    undef_method :x
end

obj = B.new
obj.x

結果-main.rb:15:in ': undefined methodx 'for#(NoMethodError)

remove_methodを使用した例2

class A 
    def x
        puts "x from A class"
    end
end

class B < A
    def x
        puts "x from B Class"
    end
    remove_method :x
end

obj = B.new
obj.x

結果-$ Ruby main.rb

aクラスのx

4

動的に計算する名前のメソッドを削除する場合は、次のような固有クラスを使用する必要があります。

class Foo
  def self.bar
    puts "bar"
  end
end

name_of_method_to_remove = :bar
eigenclass = class << Foo; self; end
eigenclass.class_eval do
  remove_method name_of_method_to_remove
end

この方法は他の答えよりも優れています。ここで私はブロックでclass_evalを使用したためです。ブロックすると現在のネームスペースが表示されるので、変数を使用してメソッドを動的に削除できます

3
edikgat