web-dev-qa-db-fra.com

Classe Ruby avec une méthode statique appelant une méthode privée?

J'ai une classe avec un certain nombre de méthodes statiques. Chacun doit appeler une méthode commune, mais j'essaie de ne pas exposer cette dernière méthode. Le rendre privé ne permettrait l'accès qu'à partir d'une instance propre de la classe? Protégé ne semble pas non plus résoudre le problème ici.

Comment puis-je éviter à do_calc d'être appelé de manière externe dans un contexte statique? (Le laisser disponible pour être appelé à partir des deux premières méthodes statiques.)

class Foo
  def self.bar
    do_calc()
  end
  def self.baz
    do_calc()
  end
  def self.do_calc
  end
end
21
yamori

Tout d’abord, static ne fait pas vraiment partie du jargon Ruby

Prenons un exemple simple:

class Bar
  def self.foo
  end
end

Il définit la méthode foo sur un objet explicite, self, qui dans cette portée renvoie la classe contenue Bar. Oui, il est possible de définir une méthode class, mais static n'a pas vraiment de sens. en rubis.

Alors private ne fonctionnerait pas, car la définition d'une méthode sur un objet explicite (par exemple def self.foo) contourne les qualificateurs d'accès et rend la méthode publique.

Ce que vous pouvez faire est d’utiliser la syntaxe class << self pour ouvrir la métaclasse de la classe qui le contient et définir les méthodes à cet endroit en tant que méthodes d’instance:

class Foo
  class << self

    def bar
      do_calc
    end

    def baz
      do_calc
    end

    private

    def do_calc
      puts "calculating..."
    end
  end
end

Cela vous donnera ce dont vous avez besoin:

Foo.bar
calculating...

Foo.baz
calculating...

Foo.do_calc
NoMethodError: private method `do_calc' called for Foo:Class
39
tompave

Vous pouvez définir une méthode de classe privée avec private_class_method comme ceci:

class Foo
  def self.bar
    do_calc
  end

  def self.baz
    do_calc
  end

  def self.do_calc
    #...
  end
  private_class_method :do_calc
end
13
spickermann

Ou à partir de Ruby 2.1:

class Foo
  def self.bar
    do_calc
  end

  private_class_method def self.do_calc
    #...
  end
end
0
mb21