web-dev-qa-db-fra.com

Supprimer / annuler la définition d'une méthode de classe

Vous pouvez définir dynamiquement une méthode de classe pour une classe comme ceci:

class Foo
end

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

Mais comment faites-vous le contraire: remove/undefine une méthode de classe? Je soupçonne le module remove_method et undef_method les méthodes peuvent être utilisées à cette fin, mais tous les exemples que j'ai vus après Googling pendant des heures ont été pour supprimer/dé-définir l'instance , pas les méthodes de classe. Ou peut-être qu'il existe une syntaxe que vous pouvez transmettre à instance_eval pour le faire également.

Merci d'avance.

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)

Lorsque vous définissez une méthode de classe comme Foo.bar, Ruby met la classe propre de Foo. Ruby ne peut pas la mettre dans Foo, car alors ce serait un méthode d'instance. Ruby crée la classe propre de Foo (aka "classe singleton"), définit la superclasse de la classe propre sur la superclasse de Foo, puis définit la superclasse de Foo sur la classe propre:

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

C'est pourquoi nous devons ouvrir la classe propre de Foo en utilisant class <<Foo pour supprimer la barre de méthodes.

63
Wayne Conrad

Cela fonctionne également pour moi (je ne sais pas s'il y a des différences entre undef et 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

Je suppose que je ne peux pas commenter la réponse d'Adrian parce que je n'ai pas assez de crédibilité, mais sa réponse m'a aidé.

Ce que j'ai trouvé: undef semble supprimer complètement la méthode de l'existence, tandis que remove_method le supprime de cette classe, mais il sera toujours défini sur les superclasses ou autres modules qui ont été étendus sur cette classe, etc.

6
Jeff Gran

Vous pouvez supprimer une méthode de deux manières simples. Le drastique

Module#undef_method( ) 

supprime toutes les méthodes, y compris celles héritées. Le plus gentil

Module#remove_method( ) 

supprime la méthode du récepteur, mais laisse les méthodes héritées seules.

Voir ci-dessous 2 exemple simple -

Exemple 1 utilisant undef_method

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

result - main.rb: 15: in ': undefined methodx 'pour # (NoMethodError)

Exemple 2 utilisant remove_method

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

Résultat - $ Ruby main.rb

x d'une classe

4
Rameshwar Vyevhare

Si vous souhaitez supprimer la méthode avec le nom qui calcule dinamiquement, vous devez utiliser des classes propres comme:

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

cette façon est meilleure que les autres réponses, car ici j'ai utilisé class_eval avec block. Comme vous bloquez maintenant voir l'espace de noms actuel, vous pouvez donc utiliser vos variables pour supprimer les méthodes de manière dinamique

3
edikgat